THRIFT-1558 Named Pipe and Anonymous Pipe transport for Windows
Patch: Peace C
git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1325020 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/README_WINDOWS b/lib/cpp/README_WINDOWS
index a955949..f4c887c 100644
--- a/lib/cpp/README_WINDOWS
+++ b/lib/cpp/README_WINDOWS
@@ -82,10 +82,17 @@
function. To target Vista, Win7 or other versions, comment out the line
#define TARGET_WIN_XP.
+Named Pipes
+===========
+- Named Pipe transport has been added in the TPipe and TPipeServer classes.
+ This is currently Windows-only (see below).
+
Known issues
============
-- Does not support named pipes. (Supported in unix through unix domain sockets).
+- Named pipe transport for *NIX has not been implemented. Domain sockets are
+ a better choice for local IPC under non-Windows OS's. *NIX named pipes
+ only support 1:1 client-server connection.
TODO
====
diff --git a/lib/cpp/libthrift.vcxproj b/lib/cpp/libthrift.vcxproj
index 286fc5b..57add63 100644
--- a/lib/cpp/libthrift.vcxproj
+++ b/lib/cpp/libthrift.vcxproj
@@ -114,6 +114,8 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
+ <ClCompile Include="src\transport\TPipe.cpp" />
+ <ClCompile Include="src\transport\TPipeServer.cpp" />
<ClCompile Include="src\transport\TServerSocket.cpp">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -179,6 +181,8 @@
<ClInclude Include="src\transport\TFileTransport.h" />
<ClInclude Include="src\transport\THttpClient.h" />
<ClInclude Include="src\transport\THttpServer.h" />
+ <ClInclude Include="src\transport\TPipe.h" />
+ <ClInclude Include="src\transport\TPipeServer.h" />
<ClInclude Include="src\transport\TServerSocket.h" />
<ClInclude Include="src\transport\TServerTransport.h" />
<ClInclude Include="src\transport\TSimpleFileTransport.h" />
@@ -248,13 +252,13 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(ProjectDir)\src\transport\;$(THIRD_PARTY)\boost\boost_1_47_0\include;$(THIRD_PARTY)\boost\boost_1_47_0\;$(THIRD_PARTY)\openssl\OpenSSL-Win32\include\;$(IncludePath)</IncludePath>
+ <IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(ProjectDir)\src\transport\;$(THIRD_PARTY)\boost\boost_1_47_0\include;$(THIRD_PARTY)\boost\boost_1_47_0\;$(THIRD_PARTY)\openssl\OpenSSL-Win32\include\;..\..\..\..\boost;..\..\..\..\boost\boost;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(ProjectDir)\src\transport\;$(THIRD_PARTY)\boost\boost_1_47_0\include;$(THIRD_PARTY)\boost\boost_1_47_0\;$(THIRD_PARTY)\openssl\OpenSSL-Win32\include\;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(ProjectDir)\src\transport\;$(THIRD_PARTY)\boost\boost_1_47_0\include;$(THIRD_PARTY)\boost\boost_1_47_0\;$(THIRD_PARTY)\openssl\OpenSSL-Win32\include\;$(IncludePath)</IncludePath>
+ <IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(ProjectDir)\src\transport\;$(THIRD_PARTY)\boost\boost_1_47_0\include;$(THIRD_PARTY)\boost\boost_1_47_0\;$(THIRD_PARTY)\openssl\OpenSSL-Win32\include\;..\..\..\..\boost;..\..\..\..\boost\boost;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(ProjectDir)\src\transport\;$(THIRD_PARTY)\boost\boost_1_47_0\include;$(THIRD_PARTY)\boost\boost_1_47_0\;$(THIRD_PARTY)\openssl\OpenSSL-Win32\include\;$(IncludePath)</IncludePath>
diff --git a/lib/cpp/libthrift.vcxproj.filters b/lib/cpp/libthrift.vcxproj.filters
index 0b0003c..0762fb4 100644
--- a/lib/cpp/libthrift.vcxproj.filters
+++ b/lib/cpp/libthrift.vcxproj.filters
@@ -96,6 +96,12 @@
<ClCompile Include="src\windows\WinFcntl.cpp">
<Filter>windows</Filter>
</ClCompile>
+ <ClCompile Include="src\transport\TPipeServer.cpp">
+ <Filter>transport</Filter>
+ </ClCompile>
+ <ClCompile Include="src\transport\TPipe.cpp">
+ <Filter>transport</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\transport\TBufferTransports.h">
@@ -212,6 +218,12 @@
<ClInclude Include="src\windows\WinFcntl.h">
<Filter>windows</Filter>
</ClInclude>
+ <ClInclude Include="src\transport\TPipe.h">
+ <Filter>transport</Filter>
+ </ClInclude>
+ <ClInclude Include="src\transport\TPipeServer.h">
+ <Filter>transport</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="protocal">
diff --git a/lib/cpp/src/transport/TPipe.cpp b/lib/cpp/src/transport/TPipe.cpp
new file mode 100644
index 0000000..2c7cf56
--- /dev/null
+++ b/lib/cpp/src/transport/TPipe.cpp
@@ -0,0 +1,209 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+#ifdef _WIN32
+
+#include "TTransportException.h"
+#include "TPipe.h"
+
+namespace apache { namespace thrift { namespace transport {
+
+using namespace std;
+
+/**
+* TPipe implementation.
+*/
+
+//---- Constructors ----
+TPipe::TPipe(HANDLE hpipe) :
+ pipename_(""),
+ hPipe_(hpipe),
+ TimeoutSeconds_(3),
+ isAnonymous(false)
+{}
+
+TPipe::TPipe(string pipename) :
+ pipename_(pipename),
+ hPipe_(INVALID_HANDLE_VALUE),
+ TimeoutSeconds_(3),
+ isAnonymous(false)
+{}
+
+TPipe::TPipe(HANDLE hPipeRd, HANDLE hPipeWrt) :
+ pipename_(""),
+ hPipe_(hPipeRd),
+ hPipeWrt_(hPipeWrt),
+ TimeoutSeconds_(3),
+ isAnonymous(true)
+{}
+
+ TPipe::TPipe() :
+ pipename_(""),
+ hPipe_(INVALID_HANDLE_VALUE),
+ TimeoutSeconds_(3)
+{}
+
+//---- Destructor ----
+TPipe::~TPipe() {
+ close();
+}
+
+
+bool TPipe::isOpen() {
+ return (hPipe_ != INVALID_HANDLE_VALUE);
+}
+
+//---------------------------------------------------------
+// Transport callbacks
+//---------------------------------------------------------
+
+bool TPipe::peek() {
+ if (!isOpen()) {
+ return false;
+ }
+ DWORD bytesavail = 0;
+ int PeekRet = 0;
+ PeekRet = PeekNamedPipe(hPipe_, NULL, 0, NULL, &bytesavail, NULL);
+ return (PeekRet != 0 && bytesavail > 0);
+}
+
+void TPipe::open() {
+ if (isOpen()) {
+ return;
+ }
+
+ int SleepInterval = 500; //ms
+ int retries = TimeoutSeconds_ * 1000 / SleepInterval;
+ for(int i=0; i<retries; i++)
+ {
+ hPipe_ = CreateFile(
+ pipename_.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ 0, // no sharing
+ NULL, // default security attributes
+ OPEN_EXISTING, // opens existing pipe
+ 0, // default attributes
+ NULL); // no template file
+
+ if (hPipe_ == INVALID_HANDLE_VALUE)
+ sleep(SleepInterval);
+ else
+ break;
+ }
+ if (hPipe_ == INVALID_HANDLE_VALUE)
+ throw TTransportException(TTransportException::NOT_OPEN, "Unable to open pipe");
+
+ // The pipe connected; change to message-read mode.
+ DWORD dwMode = PIPE_READMODE_MESSAGE;
+ int fSuccess = SetNamedPipeHandleState(
+ hPipe_, // pipe handle
+ &dwMode, // new pipe mode
+ NULL, // don't set maximum bytes
+ NULL); // don't set maximum time
+ if (fSuccess == 0)
+ {
+ throw TTransportException(TTransportException::NOT_OPEN, "SetNamedPipeHandleState failed");
+ close();
+ }
+}
+
+
+void TPipe::close() {
+ if (isOpen())
+ {
+ CloseHandle(hPipe_);
+ hPipe_ = INVALID_HANDLE_VALUE;
+ }
+}
+
+uint32_t TPipe::read(uint8_t* buf, uint32_t len) {
+ if (!isOpen())
+ throw TTransportException(TTransportException::NOT_OPEN, "Called read on non-open pipe");
+
+ DWORD cbRead;
+ int fSuccess = ReadFile(
+ hPipe_, // pipe handle
+ buf, // buffer to receive reply
+ len, // size of buffer
+ &cbRead, // number of bytes read
+ NULL); // not overlapped
+
+ if ( !fSuccess && GetLastError() != ERROR_MORE_DATA )
+ return 0; // No more data, possibly because client disconnected.
+
+ return cbRead;
+}
+
+void TPipe::write(const uint8_t* buf, uint32_t len) {
+ if (!isOpen())
+ throw TTransportException(TTransportException::NOT_OPEN, "Called write on non-open pipe");
+
+ HANDLE WritePipe = isAnonymous? hPipeWrt_: hPipe_;
+ DWORD cbWritten;
+ int fSuccess = WriteFile(
+ WritePipe, // pipe handle
+ buf, // message
+ len, // message length
+ &cbWritten, // bytes written
+ NULL); // not overlapped
+
+ if ( !fSuccess)
+ throw TTransportException(TTransportException::NOT_OPEN, "Write to pipe failed");
+}
+
+
+//---------------------------------------------------------
+// Accessors
+//---------------------------------------------------------
+
+string TPipe::getPipename() {
+ return pipename_;
+}
+
+void TPipe::setPipename(std::string pipename) {
+ pipename_ = pipename;
+}
+
+HANDLE TPipe::getPipeHandle() {
+ return hPipe_;
+}
+
+void TPipe::setPipeHandle(HANDLE pipehandle) {
+ hPipe_ = pipehandle;
+}
+
+HANDLE TPipe::getWrtPipeHandle() {
+ return hPipeWrt_;
+}
+
+void TPipe::setWrtPipeHandle(HANDLE pipehandle) {
+ hPipeWrt_ = pipehandle;
+}
+
+long TPipe::getConnectTimeout() {
+ return TimeoutSeconds_;
+}
+
+void TPipe::setConnectTimeout(long seconds) {
+ TimeoutSeconds_ = seconds;
+}
+
+}}} // apache::thrift::transport
+
+#endif //_WIN32
diff --git a/lib/cpp/src/transport/TPipe.h b/lib/cpp/src/transport/TPipe.h
new file mode 100644
index 0000000..bca3e27
--- /dev/null
+++ b/lib/cpp/src/transport/TPipe.h
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _THRIFT_TRANSPORT_TPIPE_H_
+#define _THRIFT_TRANSPORT_TPIPE_H_ 1
+#ifdef _WIN32
+
+#include "TTransport.h"
+#include "TVirtualTransport.h"
+
+namespace apache { namespace thrift { namespace transport {
+
+/**
+ * Windows Pipes implementation of the TTransport interface.
+ *
+ */
+class TPipe : public TVirtualTransport<TPipe> {
+ public:
+
+ // Constructs a new pipe object.
+ TPipe();
+ // Named pipe constructors -
+ TPipe(HANDLE hPipe);
+ TPipe(std::string path);
+ // Anonymous pipe -
+ TPipe(HANDLE hPipeRd, HANDLE hPipeWrt);
+
+ // Destroys the pipe object, closing it if necessary.
+ virtual ~TPipe();
+
+ // Returns whether the pipe is open & valid.
+ virtual bool isOpen();
+
+ // Checks whether more data is available in the pipe.
+ virtual bool peek();
+
+ // Creates and opens the named/anonymous pipe.
+ virtual void open();
+
+ // Shuts down communications on the pipe.
+ virtual void close();
+
+ // Reads from the pipe.
+ virtual uint32_t read(uint8_t* buf, uint32_t len);
+
+ // Writes to the pipe.
+ virtual void write(const uint8_t* buf, uint32_t len);
+
+
+ //Accessors
+ std::string getPipename();
+ void setPipename(std::string pipename);
+ HANDLE getPipeHandle(); //doubles as the read handle for anon pipe
+ void setPipeHandle(HANDLE pipehandle);
+ HANDLE getWrtPipeHandle();
+ void setWrtPipeHandle(HANDLE pipehandle);
+ long getConnectTimeout();
+ void setConnectTimeout(long seconds);
+
+ private:
+ std::string pipename_;
+ //Named pipe handles are R/W, while anonymous pipes are one or the other (half duplex).
+ HANDLE hPipe_, hPipeWrt_;
+ long TimeoutSeconds_;
+ bool isAnonymous;
+
+};
+
+}}} // apache::thrift::transport
+
+#endif //_WIN32
+#endif // #ifndef _THRIFT_TRANSPORT_TPIPE_H_
+
diff --git a/lib/cpp/src/transport/TPipeServer.cpp b/lib/cpp/src/transport/TPipeServer.cpp
new file mode 100644
index 0000000..6f2f73d
--- /dev/null
+++ b/lib/cpp/src/transport/TPipeServer.cpp
@@ -0,0 +1,313 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifdef _WIN32
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <cstring>
+
+#include "TPipe.h"
+#include "TPipeServer.h"
+#include <boost/shared_ptr.hpp>
+#include <AccCtrl.h>
+#include <Aclapi.h>
+
+namespace apache { namespace thrift { namespace transport {
+
+using namespace std;
+using boost::shared_ptr;
+
+//---- Constructors ----
+TPipeServer::TPipeServer(string pipename, uint32_t bufsize) :
+ pipename_(pipename),
+ bufsize_(bufsize),
+ hPipe_(INVALID_HANDLE_VALUE),
+ isAnonymous(false),
+ maxconns_(TPIPE_SERVER_MAX_CONNS_DEFAULT)
+ {}
+
+TPipeServer::TPipeServer(string pipename, uint32_t bufsize, uint32_t maxconnections) :
+ pipename_(pipename),
+ bufsize_(bufsize),
+ hPipe_(INVALID_HANDLE_VALUE),
+ isAnonymous(false)
+ { //Restrict maxconns_ to 1-255
+ if(maxconnections == 0)
+ maxconns_ = 1;
+ else if (maxconnections > 255)
+ maxconns_ = 255;
+ else
+ maxconns_ = maxconnections;
+ }
+
+TPipeServer::TPipeServer(string pipename) :
+ pipename_(pipename),
+ bufsize_(1024),
+ hPipe_(INVALID_HANDLE_VALUE),
+ isAnonymous(false),
+ maxconns_(TPIPE_SERVER_MAX_CONNS_DEFAULT)
+ {}
+
+TPipeServer::TPipeServer(int bufsize) :
+ pipename_(""),
+ bufsize_(bufsize),
+ hPipe_(INVALID_HANDLE_VALUE),
+ isAnonymous(true),
+ maxconns_(1)
+ {
+ //The anonymous pipe needs to be created first so that the server can
+ //pass the handles on to the client before the serve (acceptImpl)
+ //blocking call.
+ if (!TCreateAnonPipe()) {
+ GlobalOutput.perror("TPipeServer Create(Anon)Pipe failed, GLE=", GetLastError());
+ throw TTransportException(TTransportException::NOT_OPEN, " TPipeServer Create(Anon)Pipe failed");
+ }
+}
+
+TPipeServer::TPipeServer() :
+ pipename_(""),
+ bufsize_(1024),
+ hPipe_(INVALID_HANDLE_VALUE),
+ isAnonymous(true),
+ maxconns_(1)
+{
+ if (!TCreateAnonPipe()) {
+ GlobalOutput.perror("TPipeServer Create(Anon)Pipe failed, GLE=", GetLastError());
+ throw TTransportException(TTransportException::NOT_OPEN, " TPipeServer Create(Anon)Pipe failed");
+ }
+}
+
+//---- Destructor ----
+TPipeServer::~TPipeServer() {
+ close();
+}
+
+//---------------------------------------------------------
+// Transport callbacks
+//---------------------------------------------------------
+
+shared_ptr<TTransport> TPipeServer::acceptImpl() {
+ shared_ptr<TPipe> client;
+
+ if(isAnonymous)
+ { //Anonymous Pipe
+ //This 0-byte read serves merely as a blocking call.
+ byte buf;
+ DWORD br;
+ int fSuccess = ReadFile(
+ hPipe_, // pipe handle
+ &buf, // buffer to receive reply
+ 0, // size of buffer
+ &br, // number of bytes read
+ NULL); // not overlapped
+
+ if ( !fSuccess && GetLastError() != ERROR_MORE_DATA ) {
+ GlobalOutput.perror("TPipeServer unable to initiate pipe comms, GLE=", GetLastError());
+ throw TTransportException(TTransportException::NOT_OPEN, " TPipeServer unable to initiate pipe comms");
+ }
+ client.reset(new TPipe(hPipe_, hPipeW_));
+ }
+ else
+ { //Named Pipe
+ int ConnectRet;
+ while (true)
+ {
+ if (!TCreateNamedPipe()) {
+ GlobalOutput.perror("TPipeServer CreateNamedPipe failed, GLE=", GetLastError());
+ throw TTransportException(TTransportException::NOT_OPEN, " TPipeServer CreateNamedPipe failed");
+ }
+
+ // Wait for the client to connect; if it succeeds, the
+ // function returns a nonzero value. If the function returns
+ // zero, GetLastError should return ERROR_PIPE_CONNECTED.
+ ConnectRet = ConnectNamedPipe(hPipe_, NULL) ?
+ TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+
+ if (ConnectRet == TRUE)
+ {
+ GlobalOutput.printf("Client connected.");
+ break;
+ }
+ else
+ {
+ close();
+ GlobalOutput.perror("TPipeServer ConnectNamedPipe GLE=", GetLastError());
+ throw TTransportException(TTransportException::NOT_OPEN, "TPipeServer: client connection failed");
+ }
+ }
+ client.reset(new TPipe(hPipe_));
+ }
+
+ return client;
+}
+
+void TPipeServer::interrupt() {
+ if(hPipe_ != INVALID_HANDLE_VALUE) {
+ CancelIo(hPipe_);
+ }
+}
+
+void TPipeServer::close() {
+ if(!isAnonymous)
+ {
+ if(hPipe_ != INVALID_HANDLE_VALUE) {
+ DisconnectNamedPipe(hPipe_);
+ CloseHandle(hPipe_);
+ hPipe_ = INVALID_HANDLE_VALUE;
+ }
+ }
+ else
+ {
+ try {
+ CloseHandle(hPipe_);
+ CloseHandle(hPipeW_);
+ CloseHandle(ClientAnonRead);
+ CloseHandle(ClientAnonWrite);
+ }
+ catch(...) {
+ GlobalOutput.perror("TPipeServer anon close GLE=", GetLastError());
+ }
+ }
+}
+
+
+bool TPipeServer::TCreateNamedPipe() {
+
+ //Windows - set security to allow non-elevated apps
+ //to access pipes created by elevated apps.
+ SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
+ PSID everyone_sid = NULL;
+ AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyone_sid);
+
+ EXPLICIT_ACCESS ea;
+ ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
+ ea.grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
+ ea.grfAccessMode = SET_ACCESS;
+ ea.grfInheritance = NO_INHERITANCE;
+ ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ ea.Trustee.ptstrName = (LPSTR)everyone_sid;
+
+ PACL acl = NULL;
+ SetEntriesInAcl(1, &ea, NULL, &acl);
+
+ PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
+ InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE);
+
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = sd;
+ sa.bInheritHandle = FALSE;
+
+ // Create an instance of the named pipe
+ hPipe_ = CreateNamedPipe(
+ pipename_.c_str(), // pipe name
+ PIPE_ACCESS_DUPLEX, // read/write access
+ PIPE_TYPE_MESSAGE | // message type pipe
+ PIPE_READMODE_MESSAGE, // message-read mode
+ maxconns_, // max. instances
+ bufsize_, // output buffer size
+ bufsize_, // input buffer size
+ 0, // client time-out
+ &sa); // default security attribute
+
+ return (hPipe_ != INVALID_HANDLE_VALUE);
+}
+
+bool TPipeServer::TCreateAnonPipe() {
+ SECURITY_ATTRIBUTES sa;
+ SECURITY_DESCRIPTOR sd; //security information for pipes
+
+ InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl(&sd, true, NULL, false);
+ sa.lpSecurityDescriptor = &sd;
+ sa.lpSecurityDescriptor = NULL;
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = true; //allow passing handle to child
+
+ if (!CreatePipe(&ClientAnonRead,&hPipeW_,&sa,0)) //create stdin pipe
+ {
+ GlobalOutput.perror("TPipeServer CreatePipe (anon) failed, GLE=", GetLastError());
+ return false;
+ }
+ if (!CreatePipe(&hPipe_,&ClientAnonWrite,&sa,0)) //create stdout pipe
+ {
+ GlobalOutput.perror("TPipeServer CreatePipe (anon) failed, GLE=", GetLastError());
+ CloseHandle(ClientAnonRead);
+ CloseHandle(hPipeW_);
+ return false;
+ }
+
+ return true;
+}
+
+
+//---------------------------------------------------------
+// Accessors
+//---------------------------------------------------------
+
+string TPipeServer::getPipename() {
+ return pipename_;
+}
+
+void TPipeServer::setPipename(std::string pipename) {
+ pipename_ = pipename;
+}
+
+int TPipeServer::getBufferSize() {
+ return bufsize_;
+}
+
+void TPipeServer::setBufferSize(int bufsize) {
+ bufsize_ = bufsize;
+}
+
+HANDLE TPipeServer::getPipeHandle() {
+ return hPipe_;
+}
+
+HANDLE TPipeServer::getWrtPipeHandle()
+{
+ return hPipeW_;
+}
+
+HANDLE TPipeServer::getClientRdPipeHandle()
+{
+ return ClientAnonRead;
+}
+
+HANDLE TPipeServer::getClientWrtPipeHandle()
+{
+ return ClientAnonWrite;
+}
+
+bool TPipeServer::getAnonymous() {
+ return isAnonymous;
+}
+
+void TPipeServer::setAnonymous(bool anon) {
+ isAnonymous = anon;
+}
+
+}}} // apache::thrift::transport
+
+#endif //_WIN32
diff --git a/lib/cpp/src/transport/TPipeServer.h b/lib/cpp/src/transport/TPipeServer.h
new file mode 100644
index 0000000..1732546
--- /dev/null
+++ b/lib/cpp/src/transport/TPipeServer.h
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _THRIFT_TRANSPORT_TSERVERWINPIPES_H_
+#define _THRIFT_TRANSPORT_TSERVERWINPIPES_H_ 1
+#ifdef _WIN32
+
+#include "TServerTransport.h"
+#include <boost/shared_ptr.hpp>
+
+#define TPIPE_SERVER_MAX_CONNS_DEFAULT 10
+
+namespace apache { namespace thrift { namespace transport {
+
+/**
+ * Windows Pipes implementation of TServerTransport.
+ */
+class TPipeServer : public TServerTransport {
+ public:
+ //Constructors
+ // Named Pipe -
+ TPipeServer(std::string pipename, uint32_t bufsize);
+ TPipeServer(std::string pipename, uint32_t bufsize, uint32_t maxconnections);
+ TPipeServer(std::string pipename);
+ // Anonymous pipe -
+ TPipeServer(int bufsize);
+ TPipeServer();
+
+ //Destructor
+ ~TPipeServer();
+
+ //Standard transport callbacks
+ //void listen(); //Unnecessary for Windows pipes
+ void interrupt();
+ void close();
+ protected:
+ boost::shared_ptr<TTransport> acceptImpl();
+
+ bool TCreateNamedPipe();
+ bool TCreateAnonPipe();
+
+ public:
+ //Accessors
+ std::string getPipename();
+ void setPipename(std::string pipename);
+ int getBufferSize();
+ void setBufferSize(int bufsize);
+ HANDLE getPipeHandle(); //Named Pipe R/W -or- Anonymous pipe Read handle
+ HANDLE getWrtPipeHandle();
+ HANDLE getClientRdPipeHandle();
+ HANDLE getClientWrtPipeHandle();
+ bool getAnonymous();
+ void setAnonymous(bool anon);
+
+ private:
+ std::string pipename_;
+ uint32_t bufsize_;
+ uint32_t maxconns_;
+ HANDLE hPipe_; //Named Pipe (R/W) or Anonymous Pipe (R)
+ HANDLE hPipeW_; //Anonymous Pipe (W)
+ HANDLE ClientAnonRead, ClientAnonWrite; //Client side anonymous pipe handles
+ //? Do we need duplicates to send to client?
+ bool isAnonymous;
+};
+
+}}} // apache::thrift::transport
+
+#endif //_WIN32
+#endif // #ifndef _THRIFT_TRANSPORT_TSERVERWINPIPES_H_
diff --git a/lib/cpp/src/windows/config.h b/lib/cpp/src/windows/config.h
index d875094..aa361ff 100644
--- a/lib/cpp/src/windows/config.h
+++ b/lib/cpp/src/windows/config.h
@@ -53,6 +53,7 @@
#include <Winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
+#pragma comment(lib, "advapi32.lib") //For security APIs in TPipeServer
// pthreads
#if 0