Browse Source

Adding ipc lib

Josh Engebretson 10 years ago
parent
commit
1ddd1d674e

+ 2 - 2
Source/Atomic/CMakeLists.txt

@@ -15,7 +15,7 @@ file (GLOB IO_SOURCE IO/*.cpp IO/*.h)
 file (GLOB RESOURCE_SOURCE Resource/*.cpp Resource/*.h)
 file (GLOB RESOURCE_SOURCE Resource/*.cpp Resource/*.h)
 file (GLOB AUDIO_SOURCE Audio/*.cpp Audio/*.h)
 file (GLOB AUDIO_SOURCE Audio/*.cpp Audio/*.h)
 file (GLOB NETWORK_SOURCE Network/*.cpp Network/*.h)
 file (GLOB NETWORK_SOURCE Network/*.cpp Network/*.h)
-file (GLOB INTERPROCESS_SOURCE Interprocess/*.cpp Interprocess/*.h)
+file (GLOB IPC_SOURCE IPC/*.cpp IPC/*.h)
 
 
 file (GLOB ATOMIC2D_SOURCE Atomic2D/*.cpp Atomic2D/*.h)
 file (GLOB ATOMIC2D_SOURCE Atomic2D/*.cpp Atomic2D/*.h)
 file (GLOB SCENE_SOURCE Scene/*.cpp Scene/*.h)
 file (GLOB SCENE_SOURCE Scene/*.cpp Scene/*.h)
@@ -56,7 +56,7 @@ endif()
 
 
 set (SOURCE_FILES ${CONTAINER_SOURCE} ${CORE_SOURCE} ${ENGINE_SOURCE} ${INPUT_SOURCE}
 set (SOURCE_FILES ${CONTAINER_SOURCE} ${CORE_SOURCE} ${ENGINE_SOURCE} ${INPUT_SOURCE}
                   ${AUDIO_SOURCE} ${IO_SOURCE} ${MATH_SOURCE} 
                   ${AUDIO_SOURCE} ${IO_SOURCE} ${MATH_SOURCE} 
-                  ${RESOURCE_SOURCE} ${PHYSICS_SOURCE} ${INTERPROCESS_SOURCE}
+                  ${RESOURCE_SOURCE} ${PHYSICS_SOURCE} ${IPC_SOURCE}
                   ${GRAPHICS_SOURCE} ${GRAPHICS_IMPL_SOURCE}
                   ${GRAPHICS_SOURCE} ${GRAPHICS_IMPL_SOURCE}
                   ${ATOMIC3D_SOURCE}
                   ${ATOMIC3D_SOURCE}
                   ${ATOMIC2D_SOURCE} ${ENVIRONMENT_SOURCE}
                   ${ATOMIC2D_SOURCE} ${ENVIRONMENT_SOURCE}

+ 18 - 0
Source/Atomic/IPC/IPCBroker.cpp

@@ -0,0 +1,18 @@
+
+#include "IPCBroker.h"
+
+namespace Atomic
+{
+
+IPCBroker::IPCBroker(Context* context) : Object(context)
+{
+
+}
+
+
+IPCBroker::~IPCBroker()
+{
+
+}
+
+}

+ 25 - 0
Source/Atomic/IPC/IPCBroker.h

@@ -0,0 +1,25 @@
+
+#pragma once
+
+#include <SimpleIPC/ipc_pipe.h>
+
+#include "../Core/Mutex.h"
+#include "../Core/Thread.h"
+#include "../Core/Object.h"
+
+namespace Atomic
+{
+
+class IPCBroker : public Object, public Thread
+{
+    OBJECT(IPCBroker);
+
+public:
+    /// Construct.
+    IPCBroker(Context* context);
+    /// Destruct.
+    virtual ~IPCBroker();
+
+};
+
+}

+ 0 - 0
Source/Atomic/Interprocess/Interprocess.cpp → Source/Atomic/IPC/IPCWorker.cpp


+ 0 - 0
Source/Atomic/Interprocess/Interprocess.h → Source/Atomic/IPC/IPCWorker.h


+ 0 - 18
Source/Atomic/Interprocess/ProcessBase.cpp

@@ -1,18 +0,0 @@
-
-#include "ProcessChannel.h"
-#include "ProcessBase.h"
-
-namespace Atomic
-{
-
-ProcessBase::ProcessBase(Context* context) : Object(context)
-{
-
-}
-
-ProcessBase::~ProcessBase()
-{
-
-}
-
-}

+ 0 - 28
Source/Atomic/Interprocess/ProcessBase.h

@@ -1,28 +0,0 @@
-#pragma once
-
-#include "../Core/Object.h"
-
-namespace Atomic
-{
-
-class ProcessChannel;
-
-class ProcessBase : public Object
-{
-
-    OBJECT(ProcessBase)
-
-public:
-
-    ProcessBase(Context* context);
-    virtual ~ProcessBase();
-
-protected:
-
-    SharedPtr<ProcessChannel> inputChannel_;
-    SharedPtr<ProcessChannel> outputChannel_;
-
-};
-
-
-}

+ 0 - 22
Source/Atomic/Interprocess/ProcessChannel.cpp

@@ -1,22 +0,0 @@
-
-#include "ProcessChannel.h"
-
-namespace Atomic
-{
-
-ProcessChannel::ProcessChannel(Context *context, Mode mode, const String& name, unsigned size, bool server) :
-    Object(context),
-    size_(size),
-    mode_(mode)
-{
-    shared_ = new Poco::SharedMemory(name.CString(), size, mode == WRITE ? Poco::SharedMemory::AM_WRITE : Poco::SharedMemory::AM_READ, 0, server);
-    buffer_ = new MemoryBuffer(shared_->begin(), size);
-}
-
-ProcessChannel::~ProcessChannel()
-{
-    delete buffer_;
-    delete shared_;
-}
-
-}

+ 0 - 35
Source/Atomic/Interprocess/ProcessChannel.h

@@ -1,35 +0,0 @@
-#pragma once
-
-#include <Poco/SharedMemory.h>
-#include "../Core/Object.h"
-#include "../IO/MemoryBuffer.h"
-
-namespace Atomic
-{
-
-/// read/write variant map
-/// reserve some space at from end for mouse/etc state
-class ProcessChannel : public Object
-{
-    OBJECT(ProcessChannel)
-
-public:
-
-    enum Mode
-    {
-        READ = 0,
-        WRITE
-    };
-
-    ProcessChannel(Context* context, Mode mode, const String& name, unsigned size, bool server = true);
-    virtual ~ProcessChannel();
-
-private:
-    Poco::SharedMemory* shared_;
-    MemoryBuffer* buffer_;
-    unsigned size_;
-    Mode mode_;
-};
-
-
-}

+ 0 - 18
Source/Atomic/Interprocess/ProcessClient.cpp

@@ -1,18 +0,0 @@
-
-#include "ProcessClient.h"
-
-namespace Atomic
-{
-
-ProcessClient::ProcessClient(Context* context) : ProcessBase(context)
-{
-
-}
-
-ProcessClient::~ProcessClient()
-{
-
-}
-
-
-}

+ 0 - 24
Source/Atomic/Interprocess/ProcessClient.h

@@ -1,24 +0,0 @@
-
-#pragma once
-
-#include "ProcessBase.h"
-
-namespace Atomic
-{
-
-class ProcessChannel;
-
-class ProcessClient : public ProcessBase
-{
-    OBJECT(ProcessClient)
-
-public:
-
-    ProcessClient(Context* context);
-    virtual ~ProcessClient();
-
-private:
-
-};
-
-}

+ 0 - 21
Source/Atomic/Interprocess/ProcessServer.cpp

@@ -1,21 +0,0 @@
-
-#include "ProcessChannel.h"
-#include "ProcessServer.h"
-#include "ProcessClient.h"
-
-namespace Atomic
-{
-
-ProcessServer::ProcessServer(Context* context) : ProcessBase(context)
-{
-    unsigned size = 1024 * 1024 * 4;
-    outputChannel_ = new ProcessChannel(context, ProcessChannel::WRITE, "ATOMIC_SERVER_WRITE", size, true);
-    inputChannel_ = new ProcessChannel(context, ProcessChannel::WRITE, "ATOMIC_SERVER_READ", size, true);
-}
-
-ProcessServer::~ProcessServer()
-{
-
-}
-
-}

+ 0 - 32
Source/Atomic/Interprocess/ProcessServer.h

@@ -1,32 +0,0 @@
-
-#pragma once
-
-#include "ProcessBase.h"
-
-namespace Atomic
-{
-
-class ProcessChannel;
-class ProcessClient;
-
-class ProcessServer : public ProcessBase
-{
-    OBJECT(ProcessServer)
-
-public:
-
-    struct ClientData
-    {
-
-    };
-
-    ProcessServer(Context* context);
-    virtual ~ProcessServer();
-
-private:
-
-    SharedPtr<ProcessClient> client_;
-
-};
-
-}

+ 1 - 0
Source/ThirdParty/CMakeLists.txt

@@ -24,6 +24,7 @@ if (NOT IOS AND NOT ANDROID AND NOT EMSCRIPTEN)
     add_subdirectory(LibCpuId)
     add_subdirectory(LibCpuId)
     add_subdirectory(SQLite)
     add_subdirectory(SQLite)
     add_subdirectory(TurboBadger)
     add_subdirectory(TurboBadger)
+    add_subdirectory(SimpleIPC)
     add_subdirectory(Poco)
     add_subdirectory(Poco)
     add_subdirectory(nativefiledialog)
     add_subdirectory(nativefiledialog)
 endif ()
 endif ()

+ 12 - 0
Source/ThirdParty/SimpleIPC/CMakeLists.txt

@@ -0,0 +1,12 @@
+
+
+
+file (GLOB HEADER_FILES *.h)
+
+if (MSVC)
+  set (SOURCE_FILES pipe_win.cpp)
+else()
+  set (SOURCE_FILES pipe_unix.cpp)
+endif()
+
+add_library(SimpleIPC ${SOURCE_FILES} ${HEADER_FILES})

+ 373 - 0
Source/ThirdParty/SimpleIPC/ipc_channel.h

@@ -0,0 +1,373 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_CHANNEL_H_
+#define SIMPLE_IPC_CHANNEL_H_
+
+#include "ipc_constants.h"
+#include "ipc_utils.h"
+#include "ipc_wire_types.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// The channel class is a controler/coordinator between the different IPC actors:
+// 1- the transport (like a pipe)
+// 2- the message encoder
+// 3- the message decoder
+// 4- the message
+//
+// The unit of communication of a channel is the message. The channel does not differenciate
+// sender or receiver and assumes that the transport is bi-directional.
+// 
+// For outgoing messages, a message is just defined as an array of WireType pointers along with
+// a message id. The encoder and decoder are loosely coupled with the message and it is the job
+// of the channel to interface them.
+//
+// Sending Requirements
+//  Encoder should implement:
+//    bool Open(int n_args)
+//    bool Close()
+//    void SetMsgId(int msg_id)
+//    bool OnWord(void* bits, int tag)
+//    bool OnString8(const string& s, int tag)
+//    bool OnString16(const wstring& s, int tag)
+//    bool OnUnixFd(int fd, int tag)
+//    bool OnWinHandle(void* handle, int tag)
+//    const void* GetBuffer(size_t* sz)
+//
+// Receiving Requirements
+//  Decoder<Handler> should implement:
+//    bool OnData(const char* buff, size_t sz)
+//    bool Success()
+//  Decoder<Handler> should call:
+//    bool Handler::OnMessageStart(int id, int n_args)
+//    bool Handler::OnWord(const void* bits, int type_id)
+//    bool Handler::OnString8(string& str, int type_id) 
+//    bool Handler::OnString16(wstring& str, int type_id)
+//
+
+namespace ipc {
+
+template <class TransportT, class EncoderT, template <class> class DecoderT>
+class Channel {
+ public:
+  static const size_t kMaxNumArgs = 10;
+  Channel(TransportT* transport) : transport_(transport), last_msg_id_(-1) {}
+
+  // This is the last message that was received. Or at least the header was
+  // correct so we could extract the message id.
+  int LastRecvMsgId() const { return last_msg_id_; }
+
+  // Sends the message (|args| + msg_id) to the other end of the connected
+  // |transport| passed to the constructor. This call can block or not depending
+  // on the transport implementation.
+  size_t Send(int msg_id, const WireType* const args[], int n_args)  {
+    EncoderT encoder;
+    encoder.Open(n_args);
+    for (int ix = 0; ix != n_args; ++ix) {
+      if (!AddMsgElement(&encoder, *args[ix]))
+        return RcErrEncoderType;
+    }
+
+    encoder.SetMsgId(msg_id);
+    if (!encoder.Close())
+      return RcErrEncoderClose;
+
+    size_t size;
+    const void* buf = encoder.GetBuffer(&size);
+    if (!buf)
+      return RcErrEncoderBuffer;
+    return transport_->Send(buf, size);
+  }
+
+  // Blocking wait for a message to arrive to from the other end of the
+  // |transport| passed in the constructor. If a valid message is received
+  // the function calls |top_dispatch| and then returns with the return
+  // value of |top_dispatch|.
+  //
+  // The DispatchT class is required to implement two functions:
+  // 1- Tm* MsgHandler(int msg_id);
+  //    The return value is a pointer to an object of a type that can handle |msg_id|.
+  //    This class must implement:
+  //    size_t Tm::OnMsgIn(int msg_id,
+  //                       ChannelT* ch,
+  //                       const WireType* const args[],
+  //                       int count);
+  //
+  // 2- void* OnNewTransport();
+  //    Returns the handle to a new transport. It also means to
+  //    create a new thread or process to handle messages over that
+  //    transport. Return NULL if this feature is not supported.
+  //
+  // Depending on the value returned by the message handler Tm::OnMsgIn(), this function
+  // loops again (if return is 0) or finishes (return non-zero), so by necessity
+  // this function never returns 0.
+  //
+  // The costume is to use ipc::OnMsgLoopNext (0) to loop and ipc::OnMsgReady (1)
+  // to terminate with no error condtion. This is desirable but not necessary.
+  //
+  template <class DispatchT>
+  size_t Receive(DispatchT* top_dispatch) {
+
+    RxHandler handler;
+    DecoderT<RxHandler> decoder(&handler);
+
+    // There are two do/while nested loops. The inner one runs until a full message
+    // has been decoded and the outer one runs until a dispatcher returns anything
+    // but a 0. The inner loop has two modes, in one it requires more external data
+    // and in the other it can keep processing what has been read so far. They are
+    // required to handle the case of reading less than a full message and when
+    // reading more than one message.
+    size_t retv = 0;
+    do {
+      size_t received = 0;
+       const char* buf = NULL;
+      do {
+        if (decoder.NeedsMoreData()) {
+          buf = transport_->Receive(&received);
+          if (!buf) {
+            // read failed.
+            return RcErrTransportRead;
+          }
+        } else {
+          buf = NULL;
+        }
+      } while (decoder.OnData(buf, received));
+
+      last_msg_id_ = handler.MsgId();
+
+      if(!decoder.Success())
+        return RcErrDecoderFormat;
+
+      size_t np = handler.GetArgCount();
+      if (np > kMaxNumArgs)
+        return RcErrDecoderArgs;
+
+      const WireType* args[kMaxNumArgs];
+      for (size_t ix = 0; ix != np; ++ix) {
+        args[ix] = &handler.GetArg(ix);
+      }
+
+      if ((handler.MsgId() == kMessagePrivNewTransport) &&
+          (np == 1) && (args[0]->GetAsBits() == NULL)) {
+        // Got special rpc to create a new transport. On the receiving side we handle it entirely
+        // here by calling OnNewTransport and then sending the reply, but on the sending side it
+        // is handled by a NewTransportHandler object so it actually uses top_dispatch->MsgHandler().
+        void* handle = top_dispatch->OnNewTransport();
+        retv = handle ? SendNewTransportMsg(handle) : ipc::OnMsgLoopNext;
+      } else {
+        // Got one regular message. Now dispatch it.
+        retv = top_dispatch->MsgHandler(handler.MsgId())->OnMsgIn(handler.MsgId(), this, args, np);
+      }
+
+      handler.Clear();
+      decoder.Reset();
+    } while(ipc::OnMsgLoopNext == retv);
+
+    return retv;
+  }
+
+  // Issues an rpc to the remote side, usually the server to get a new transport identifier, it is
+  // some OS-dependent value that can be used to create a pipe or domain socket. It implies that
+  // somehow the remote side will spin some machinery to answer messages sent this way.
+  void* InitNewTransport() {
+    size_t rc = SendNewTransportMsg(NULL);
+    if (rc)
+      return NULL;
+    NewTransportHandler handler;
+    rc = Receive(&handler);
+    if (rc != ipc::OnMsgReady)
+      return NULL;
+    return handler.Handle();
+  }
+
+  // This class is using during receiving as the callback handler for the decoder.
+  // Its function is to receive each decoded type and transform it into WireType objects.
+  //
+  // This class would be private except that we have unit tests that use it as
+  // convenience. Treat it as private though.
+  class RxHandler {
+   public:
+    RxHandler() : msg_id_(-1) {} 
+
+    // Called when a valid message preamble is received.
+    bool OnMessageStart(int id, int n_args) {
+      msg_id_ = id;
+      if (n_args > kMaxNumArgs)
+        return false;
+      return true;
+    }
+
+    // Handles the word-sized 'value' decoded types.
+    bool OnWord(const void* bits, int type_id) {
+      switch (type_id) {
+        case ipc::TYPE_INT32:
+          list_.push_back(WireType(*reinterpret_cast<const int*>(bits)));
+          break;
+        case ipc::TYPE_UINT32:
+          list_.push_back(WireType(*reinterpret_cast<const unsigned int*>(bits)));
+          break;
+        case ipc::TYPE_LONG32:
+          list_.push_back(WireType(*reinterpret_cast<const long*>(bits)));
+          break;
+        case ipc::TYPE_ULONG32:
+          list_.push_back(WireType(*reinterpret_cast<const unsigned long*>(bits)));
+          break;
+        case ipc::TYPE_CHAR8:
+          list_.push_back(WireType(*reinterpret_cast<const char*>(bits)));
+          break;
+        case ipc::TYPE_CHAR16:
+          list_.push_back(WireType(*reinterpret_cast<const wchar_t*>(bits)));
+          break;
+        case ipc::TYPE_VOIDPTR:
+          list_.push_back(WireType(reinterpret_cast<const void*>(
+              *reinterpret_cast<const unsigned long*>(bits))));
+          break;
+        case ipc::TYPE_NULLSTRING8:
+          list_.push_back(WireType(static_cast<char*>(NULL)));
+          break;
+        case ipc::TYPE_NULLSTRING16:
+          list_.push_back(WireType(static_cast<wchar_t*>(NULL)));
+          break;
+        case ipc::TYPE_NULLBARRAY:
+          list_.push_back(WireType(ipc::ByteArray(0, NULL)));
+          break;
+        default:
+          return false;
+      }
+      return true;
+    }
+
+    // Handles the byte-sized arrays.
+    bool OnString8(IPCString& str, int type_id) {
+      switch (type_id) {
+        case ipc::TYPE_STRING8:
+          list_.push_back(WireType(str.c_str()));
+          break;
+        case ipc::TYPE_BARRAY:
+          list_.push_back(WireType(ByteArray(str.size(), str.c_str())));
+          break;
+        default: 
+          return false;
+      }
+      return true;
+    }
+
+    // Handles the wchar-sized arrays.
+    bool OnString16(IPCWString& str, int type_id) {
+      switch (type_id) {
+        case ipc::TYPE_STRING16:
+          list_.push_back(WireType(str.c_str()));
+          break;
+        default: 
+          return false;
+      }
+      return true;
+    }
+
+    int MsgId() const { return msg_id_; }
+    
+    const WireType& GetArg(size_t ix) {
+      return list_[ix];
+    }
+
+    size_t GetArgCount() const { return list_.size(); }
+
+    void Clear() {
+      list_.clear();
+      msg_id_ = -1;
+    }
+
+  private:
+    typedef FixedArray<WireType, (kMaxNumArgs + 1)> RxList;
+    RxList list_;
+    int msg_id_;
+  };
+
+private:
+  // Class to handle the client side of the internal kMessagePrivNewTransport message
+  // which carries a transport id, usually a handle value on windows.
+  class NewTransportHandler {
+  public:
+    NewTransportHandler() : t_handle_(NULL) {}
+
+    NewTransportHandler* MsgHandler(int) {
+      return this;
+    }
+
+    size_t OnMsgIn(int msg_id, Channel*, const WireType* const args[], int count) {
+      if ((count != 1) && (msg_id != kMessagePrivNewTransport))
+        return RcErrNewTransport;
+      t_handle_ = args[0]->GetAsBits();
+      return ipc::OnMsgReady;
+    }
+
+    void* OnNewTransport() { return NULL; }
+    void* Handle() const { return t_handle_; }
+  
+  private:
+    void* t_handle_;
+  };
+
+  size_t SendNewTransportMsg(void* handle) {
+    WireType wt(handle);
+    const WireType* const arg[] = { &wt };
+    return Send(kMessagePrivNewTransport, arg, 1);
+  }
+
+  // Uses |EncoderT| to encode one message element in the outgoing buffer.
+  bool AddMsgElement(EncoderT* encoder, const WireType& wtype) {
+    switch (wtype.Id()) {
+      case ipc::TYPE_NONE:
+        return false;
+
+      case ipc::TYPE_INT32:
+      case ipc::TYPE_UINT32:
+      case ipc::TYPE_CHAR8:
+      case ipc::TYPE_CHAR16:
+      case ipc::TYPE_LONG32:
+      case ipc::TYPE_ULONG32:
+      case ipc::TYPE_VOIDPTR:
+          return encoder->OnWord(wtype.GetAsBits(), wtype.Id());
+
+      case ipc::TYPE_STRING8:
+      case ipc::TYPE_BARRAY: {
+          IPCString ctemp;
+          wtype.GetString8(&ctemp);
+          return encoder->OnString8(ctemp, wtype.Id());
+        }
+
+      case ipc::TYPE_STRING16: {
+          IPCWString wtemp;
+          wtype.GetString16(&wtemp);
+          return encoder->OnString16(wtemp, wtype.Id());
+        }
+
+      case ipc::TYPE_NULLSTRING8:
+      case ipc::TYPE_NULLSTRING16:
+      case ipc::TYPE_NULLBARRAY:
+        return encoder->OnWord(wtype.GetAsBits(), wtype.Id());
+
+      default:
+        return false;
+    }
+  }
+
+  TransportT* transport_;
+  int last_msg_id_;
+};
+
+}  // namespace ipc.
+
+#endif // SIMPLE_IPC_CHANNEL_H_
+

+ 420 - 0
Source/ThirdParty/SimpleIPC/ipc_codec.h

@@ -0,0 +1,420 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_CODEC_H_
+#define SIMPLE_IPC_CODEC_H_
+
+#include "os_includes.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// This file contains the default encoder & decoder for IPC. It does no compression and every
+// encoded element is aligned to the machine word size. For a 32 bit machine, this is how the
+// format on the final buffer looks like:
+//
+// bytes what
+// 0     start of header mark
+// 4     msg id
+// 8     element count (1 to N)
+// 12    data count (in 4 byte units
+// 16    first element tag
+// 20    second element tag
+// +4    .......
+//       last element type
+//       start of data mark     
+//       first element value
+//       second element value
+//       .......
+//       end of data mark
+//
+// As you can see the element tags are not interleaved with the element value, all the tags
+// are within the header, and all values follow afterwards.
+//
+// This code does not assume any knowledge of the Channel type. For example is unaware of WireType
+// so it takes a generic |tag| that in the case of using it with the standard ipc::Channel they
+// would be ipc::TYPE_XXXXX. However, arrays (bytes and strings) are treated differently in which
+// the tag is actually 'enhanced' with an extra bit in the form of ENC_STRN08 or ENC_STRN16.
+
+namespace ipc {
+
+class Encoder {
+public:
+  enum {
+    ENC_HEADER = 0x4d4f524b,
+    ENC_STARTD = 0x4b524f4d,
+    ENC_ENDDAT = 0x474e4142,
+    ENC_STRN08 = 1<<30,
+    ENC_STRN16 = 1<<31
+  };
+
+  Encoder() : index_(-1) {}
+
+  bool Open(int count) {
+    data_.clear();
+    data_.reserve(count * 5);
+    data_.resize(count + 5);
+    index_ = -1;
+    SetHeaderNext(ENC_HEADER);  // 0
+    SetHeaderNext(0);           // 1
+    SetHeaderNext(count);       // 2
+    SetHeaderNext(0);           // 3
+    return true;
+  }
+
+  bool Close() {
+    SetHeaderNext(ENC_STARTD);
+    PushBack(ENC_ENDDAT);
+    SetDataSizeHeader();
+    return true;
+  }
+  
+  bool OnWord(void* bits, int tag) {
+    SetHeaderNext(tag);
+    data_.push_back(bits);
+    return true;
+  };
+
+  bool OnString8(const IPCString& s, int tag) {
+    SetHeaderNext(tag | ENC_STRN08);
+    PushBack(s.size());
+    if (s.size()) AddStr(s);
+    return true;
+  }
+
+  bool OnString16(const IPCWString& s, int tag) {
+    SetHeaderNext(tag | ENC_STRN16);
+    PushBack(s.size());
+    if (s.size()) AddStr(s);
+    return true;
+  }
+
+  bool OnUnixFd(int /*fd*/, int tag) {
+    SetHeaderNext(tag);
+    // $$ implement
+    return true;
+  }
+
+  bool OnWinHandle(void* /*handle*/, int tag) {
+    SetHeaderNext(tag);
+    // $$ implement
+    return true;
+  }
+
+  const void* GetBuffer(size_t* sz) {
+    *sz = data_.size() * sizeof(void*);
+    return &data_[0];
+  }
+
+  void SetMsgId(int id) {
+    data_[1] = reinterpret_cast<void*>(id);
+  }
+
+private:
+
+  void SetHeaderNext(int v) {
+    data_[++index_] = reinterpret_cast<void*>(v);
+  }
+
+  void SetDataSizeHeader() {
+    data_[3] = reinterpret_cast<void*>(data_.size());
+  }
+
+  void PushBack(int v) {
+    data_.push_back(reinterpret_cast<void*>(v));
+  }
+
+  void PushBack(unsigned int v) {
+    data_.push_back(reinterpret_cast<void*>(v));
+  }
+
+  template <typename StringT> 
+  void AddStr(const StringT& s ) {
+    const int times = sizeof(IPCVoidPtrVector::value_type) / sizeof(s[0]);
+    size_t it = 0;
+    do {
+      unsigned int v = 0;
+      for (int ix = 0; ix != times; ++ix) {
+        if (it == s.size())
+          break;
+        v |= PackChar(s[it], ix);
+        ++it;
+      }
+      PushBack(v);
+    } while (it != s.size());
+  }
+
+  unsigned int PackChar(char c, int offset) const {
+    return static_cast<unsigned char>(c) << (offset * 8);
+  }
+
+#if 0
+  unsigned int PackChar(wchar_t c, int offset) const {
+    unsigned int u = (static_cast<unsigned char>(c) << 8) | static_cast<unsigned char>(c >> 8)
+    return  u << offset * 16;
+  }
+#endif
+
+  unsigned int PackChar(wchar_t c, int offset) const {
+    const char* t = reinterpret_cast<const char*>(&c);
+    return  (PackChar(t[0], 0) | PackChar(t[1], 1)) << (offset * 16);
+  }
+
+  IPCVoidPtrVector data_;
+  int index_;
+};
+
+
+template <typename HandlerT>
+class Decoder {
+public:
+  Decoder(HandlerT* handler) : handler_(handler) {
+    Reset();
+  }
+
+  bool OnData(const char* buff, size_t sz) {
+    if (buff) {
+      data_.insert(data_.end(), buff, buff + sz);
+    } else if (!data_.size()) {
+      return true;
+    }
+    if (data_.size() % sizeof(void*) == 0) {
+      return (RunDecoder() == DEC_MOREDATA);
+    }
+    return true;
+  }
+
+  bool Success() { return state_ == DEC_S_DONE; }
+
+  bool NeedsMoreData() const {
+    return (data_.size() == 0) || (res_ == DEC_MOREDATA); 
+  }
+
+  void Reset() {
+    state_ = DEC_S_START;
+    e_count_ = -1;
+    d_count_ = static_cast<size_t>(-1);
+    next_char_ = 0;
+    res_ = DEC_NONE;
+  }
+
+private:
+  // States of the decoder state machine, for a single message
+  // they are basically traveled from the first to the last and
+  // there is no state that means 'error'. When an error happens
+  // the state machine stops at the state that caused it.
+  enum State {
+    DEC_S_START,
+    DEC_S_HEADSZ,
+    DEC_S_EDATA,
+    DEC_S_STOP,
+    DEC_S_DONE
+  };
+
+  // The possible results of running one step on the state machine.
+  // DEC_LOOPAGAIN causes the state machine to be spin up one more
+  // time while the others cause it to return to the caller so
+  // it can provide more data, handle a decoding error or process
+  // a ready message.
+  enum Result {
+    DEC_NONE,
+    DEC_LOOPAGAIN,
+    DEC_MOREDATA,
+    DEC_DONE,
+    DEC_ERROR
+  };
+
+  Result RunDecoder() {
+    do {
+      res_ = DecodeStep();
+    } while (DEC_LOOPAGAIN == res_);
+    return res_;
+  }
+
+  Result DecodeStep() {
+    switch(state_) {
+      case DEC_S_START: return StateStart();
+      case DEC_S_HEADSZ: return StateHeader();
+      case DEC_S_EDATA: return StateData();
+      case DEC_S_STOP: return StateDone();
+      default: break;
+    }
+    return DEC_ERROR;
+  }
+
+  Result StateStart() {
+    // We need at least the first 4 ints.
+    if (!HasEnoughUnProcessed(4))
+      return DEC_MOREDATA;
+    int i0 = ReadNextInt();
+    if (Encoder::ENC_HEADER != i0)
+      return DEC_ERROR;
+    int msg_id = ReadNextInt();
+    if (msg_id < 0)
+      return DEC_ERROR;
+    e_count_ = ReadNextInt();
+    if ((e_count_ < 1) || (e_count_ > 100))
+      return DEC_ERROR;
+    d_count_ = ReadNextInt();
+    if ((d_count_ < 5) || (d_count_ > (8 * 1024 * 1024)))
+      return DEC_ERROR;
+    // Done with the key header piece.
+    if (!handler_->OnMessageStart(msg_id, e_count_))
+      return DEC_ERROR;
+    // The handler is willing to accept the message.
+    d_count_ -= 4;
+    state_ = DEC_S_HEADSZ;
+    if (HasEnoughUnProcessed(1))
+      return DEC_LOOPAGAIN;
+    return DEC_MOREDATA;
+  }
+
+  Result StateHeader() {
+    if (!HasEnoughUnProcessed(e_count_ + 1))
+      return DEC_MOREDATA;
+    //items_.reserve(e_count_);
+    for (int ix = 0; ix != e_count_; ++ix) {
+      items_.push_back(ReadNextInt());
+    }
+    int i0 = ReadNextInt();
+    if (i0 != Encoder::ENC_STARTD)
+      return DEC_ERROR;
+    // Done with all the header
+    d_count_ -= e_count_ + 1;
+    if (!items_.size()) {
+      // That's it, no data.
+      state_ = DEC_S_STOP;
+      if (HasEnoughUnProcessed(1))
+        return DEC_LOOPAGAIN;
+      return DEC_MOREDATA;
+    }
+    // We got data to process. Each datum, even null strings
+    // take at least 4 bytes.
+    if (d_count_ < items_.size())
+      return DEC_ERROR;
+
+    state_ = DEC_S_EDATA;
+    if (HasEnoughUnProcessed(1))
+      return DEC_LOOPAGAIN;
+    return DEC_MOREDATA;
+  }
+
+  Result StateData() {
+    if (!HasEnoughUnProcessed(d_count_))
+      return DEC_MOREDATA;
+    size_t ix = 0;
+    do {
+        int tag = items_[ix];
+        if (tag & Encoder::ENC_STRN08) {
+          tag &= ~Encoder::ENC_STRN08;
+          ReadNextStr8(tag);
+        } else if (tag & Encoder::ENC_STRN16) {
+          tag &= ~Encoder::ENC_STRN16;
+          ReadNextStr16(tag);
+        } else {
+          --d_count_;
+          if (!handler_->OnWord(ReadNextVoidPtr(), tag)) {
+            return DEC_ERROR;
+          }
+        }
+        ++ix;
+        if (items_.size() == ix) {
+          items_.clear();
+          state_ = DEC_S_STOP;
+          if (HasEnoughUnProcessed(1))
+            return DEC_LOOPAGAIN;
+          return DEC_MOREDATA;
+        }
+    } while (HasEnoughUnProcessed(1));
+    return DEC_MOREDATA;
+  }
+
+  Result StateDone() {
+    if (!HasEnoughUnProcessed(1))
+      return DEC_MOREDATA;
+    --d_count_;
+    int it0 = ReadNextInt();
+    if (Encoder::ENC_ENDDAT != it0)
+      return DEC_ERROR;
+
+    data_.erase(data_.begin(), data_.begin() + next_char_);
+    state_ = DEC_S_DONE;
+    return DEC_DONE;
+  }
+
+  int ReadNextInt() {
+    int v  = *reinterpret_cast<int*>(&data_[next_char_]);
+    next_char_ += sizeof(void*);
+    return v;
+  }
+
+  bool ReadNextStr8(int tag) {
+    size_t str_sz = ReadNextInt();
+    size_t sz_rounded = RoundUpToNextVoidPtr(str_sz);
+    if(!HasEnoughUnProcessed(sz_rounded))
+      return false;
+    const char* beg = &data_[next_char_];
+    IPCString str;
+    str.assign(beg, str_sz);
+    next_char_ += sz_rounded * sizeof(void*);
+    handler_->OnString8(str, tag);
+    return true;
+  }
+
+  bool ReadNextStr16(int tag) {
+    size_t str_sz = ReadNextInt();
+    size_t byte_sz = str_sz * sizeof(wchar_t);
+    size_t sz_rounded = RoundUpToNextVoidPtr(byte_sz);
+    if(!HasEnoughUnProcessed(sz_rounded))
+      return false;
+    const wchar_t* beg = reinterpret_cast<wchar_t*>(&data_[next_char_]);
+    IPCWString str;
+    str.assign(beg, str_sz);
+    next_char_ += sz_rounded * sizeof(void*);
+    handler_->OnString16(str, tag);
+    return true;
+  }
+
+  void* ReadNextVoidPtr() {
+    void* v = &data_[next_char_];
+    next_char_ += sizeof(void*);
+    return v;
+  }
+
+  char ReadNextChar() {
+    return data_[next_char_++];
+  }
+
+  bool HasEnoughUnProcessed(int ints) {
+    return ((data_.size() - next_char_) >= (ints * sizeof(void*)));
+  }
+
+  int RoundUpToNextVoidPtr(int sz) {
+    return (sz + (sizeof(void*)-1))/sizeof(void*);
+  }        
+
+  HandlerT* handler_;
+
+  IPCCharVector data_;
+  IPCIntVector items_;
+
+  State state_;
+  int e_count_;
+  size_t d_count_;
+  int next_char_;
+  Result res_;
+};
+
+
+}  // namespace ipc.
+
+#endif  // SIMPLE_IPC_CODEC_H_

+ 65 - 0
Source/ThirdParty/SimpleIPC/ipc_constants.h

@@ -0,0 +1,65 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_CONSTANTS_H_
+#define SIMPLE_IPC_CONSTANTS_H_
+
+namespace ipc {
+
+// No error is always 0. Positive values are reserved for the application
+// while negative errors are reserved for the IPC library.
+
+const size_t RcOK                   = 0;
+const size_t RcErrEncoderClose      = static_cast<size_t>(-1);
+const size_t RcErrEncoderBuffer     = static_cast<size_t>(-2);
+const size_t RcErrEncoderType       = static_cast<size_t>(-3);
+const size_t RcErrTransportWrite    = static_cast<size_t>(-4);
+const size_t RcErrTransportRead     = static_cast<size_t>(-5);
+const size_t RcErrTransportConnect  = static_cast<size_t>(-6);
+const size_t RcErrDecoderFormat     = static_cast<size_t>(-7);
+const size_t RcErrDecoderArgs       = static_cast<size_t>(-8);
+const size_t RcErrNewTransport      = static_cast<size_t>(-9);
+const size_t RcErrBadMessageId      = static_cast<size_t>(-10);
+
+// For the return on obj.OnMsg() when calling Channel::Receive(obj) there
+// are two critical values:
+// - OnMsgLoopNext:  typically always returned by the server OnMsg()
+//                   so it goes to process the next message
+// - OnMsgAppErrorBase: typically always returned by the client OnMsg()
+//                   so Receive() exits.
+//
+const size_t OnMsgLoopNext      = 0;  // Loop again and read another message.
+const size_t OnMsgReady         = 1;  // Done receiving.
+const size_t OnMsgAppErrorBase  = 2;  // Application specific errors start here.
+
+// It is important to note that OnMsgLoopNext is 0 which is also RcOK. This
+// enables the following server (broker) side pattern
+//
+//  size_t OnMsg(ChannelT* ch, param1, param2,...) {
+//    ... operation here
+//    return SendMsg(kRepyId, ch, result1, ..);
+//  }
+
+
+// Reserved messages ids. User messages should start at kMessagePrivLastId and
+// above.
+const int kMessagePrivNewTransport   = 1;
+const int kMessagePrivControl        = 2;
+const int kMessagePrivLastId         = 3;
+
+
+}  // namespace ipc.
+
+#endif // SIMPLE_IPC_CONSTANTS_H_
+

+ 315 - 0
Source/ThirdParty/SimpleIPC/ipc_msg_dispatch.h

@@ -0,0 +1,315 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_MSG_DISPATCH_H_
+#define SIMPLE_IPC_MSG_DISPATCH_H_
+
+#include "ipc_constants.h"
+#include "ipc_wire_types.h"
+
+// The two classes in this file ipc::MsgIn and ipc::MsgOut are nice wrappers to
+// the two common tasks of sending a message and receiving a message. They are
+// not required but highly recomended.
+
+// This templated class will be specialized for each message id. This
+// can be done explicitly or via the DEFINE_IPC_MSG_CONV macros.
+template<int MsgId>
+class MsgParamConverter;
+
+namespace ipc {
+//
+// Receives a message with id=|MsgId| and calls the appropiate overload of
+// OnMsg on the derived |DerivedT| class. To use this class you need to define
+// the format of the message using DEFINE_IPC_MSG_CONV or creating the specific
+// overload of MsgParamConverter<MsgId> by hand.
+//
+template <int MsgId, class DerivedT, typename ChannelT>
+class MsgIn {
+public:
+  // Int2Type is a handy template that given an integer generates a unique type. It is
+  // used to dispatch a message to the right overload of DispatchImpl based on the
+  // number of parameters without having to use printf-style elipsis calling which
+  // loses the original type.
+  template <int v> struct Int2Type {
+    enum { value = v };
+  };
+
+  enum { MSG_ID = MsgId };
+
+  typedef MsgParamConverter<MsgId> PC;
+
+  size_t OnMsgIn(int msg_id, ChannelT* ch, const WireType* const args[], int count) {
+    if (MsgId != msg_id) {
+      return static_cast<size_t>(ipc::RcErrBadMessageId);
+    }
+    if (count != PC::kNumParams)
+      return static_cast<DerivedT*>(this)->OnMsgArgCountError(count);
+    try {
+      return DispatchImpl(Int2Type<PC::kNumParams>(), ch, args);
+    } catch(int& code) {
+      return static_cast<DerivedT*>(this)->OnMsgArgConvertError(code);
+    }
+  }
+
+  // This function is meant simplify the scope specifier when calling OnMsgIn.
+  // We use it when we have to override OnMsgIn and we need to call the original. 
+  size_t OnMsgInX(int msg_id, ChannelT* ch, const WireType* const args[], int count) {
+    return OnMsgIn(msg_id, ch, args, count);
+  }
+
+  DerivedT* MsgHandler(int msg_id) {
+    return (MsgId == msg_id) ? static_cast<DerivedT*>(this) : NULL;
+  }
+
+protected:
+  size_t DispatchImpl(const Int2Type<0>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch);
+  }
+
+  size_t DispatchImpl(const Int2Type<1>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0());
+  }
+
+  size_t DispatchImpl(const Int2Type<2>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1());
+  }
+
+  size_t DispatchImpl(const Int2Type<3>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1(), PC(args[2]).p2());
+  }
+
+  size_t DispatchImpl(const Int2Type<4>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1(), PC(args[2]).p2(),
+                                               PC(args[3]).p3());
+  }
+
+  size_t DispatchImpl(const Int2Type<5>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1(), PC(args[2]).p2(),
+                                               PC(args[3]).p3(), PC(args[4]).p4());
+  }
+
+  size_t DispatchImpl(const Int2Type<6>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1(), PC(args[2]).p2(),
+                                               PC(args[3]).p3(), PC(args[4]).p4(), PC(args[5]).p5());
+  }
+
+  size_t DispatchImpl(const Int2Type<7>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1(), PC(args[2]).p2(),
+                                               PC(args[3]).p3(), PC(args[4]).p4(), PC(args[5]).p5(),
+                                               PC(args[6]).p6());
+  }
+
+  size_t DispatchImpl(const Int2Type<8>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1(), PC(args[2]).p2(),
+                                               PC(args[3]).p3(), PC(args[4]).p4(), PC(args[5]).p5(),
+                                               PC(args[6]).p6(), PC(args[7]).p7());
+  }
+
+  size_t DispatchImpl(const Int2Type<9>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1(), PC(args[2]).p2(),
+                                               PC(args[3]).p3(), PC(args[4]).p4(), PC(args[5]).p5(),
+                                               PC(args[6]).p6(), PC(args[7]).p7(), PC(args[8]).p8());
+  }
+
+  size_t DispatchImpl(const Int2Type<10>&, ChannelT* ch, const WireType* const args[]) {
+    return static_cast<DerivedT*>(this)->OnMsg(ch, PC(args[0]).p0(), PC(args[1]).p1(), PC(args[2]).p2(),
+                                               PC(args[3]).p3(), PC(args[4]).p4(), PC(args[5]).p5(),
+                                               PC(args[6]).p6(), PC(args[7]).p7(), PC(args[8]).p8(),
+                                               PC(args[9]).p9());
+  }
+
+};
+
+// Sends a message with id=|msg_id|. Basically wraps the tedious task of creating the
+// appropiate WireType array and calling the channel::Send with the correct number of params.
+template <typename ChannelT>
+class MsgOut {
+ protected:
+  size_t SendMsg(int msg_id, ChannelT* ch)  {
+    return ch->Send(msg_id, NULL, 0);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0) {
+    const WireType* const args[] = { &a0 };
+    return ch->Send(msg_id, args, 1);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1) {
+    const WireType* const args[] = { &a0, &a1 };
+    return ch->Send(msg_id, args, 2);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1,
+    const WireType& a2) {
+    const WireType* const args[] = { &a0, &a1, &a2 };
+    return ch->Send(msg_id, args, 3);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1, const WireType& a2,
+      const WireType& a3) {
+    const WireType* const args[] = { &a0, &a1, &a2, &a3 };
+    return ch->Send(msg_id, args, 4);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1, const WireType& a2,
+      const WireType& a3, const WireType& a4) {
+    const WireType* const args[] = { &a0, &a1, &a2, &a3, &a4 };
+    return ch->Send(msg_id, args, 5);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1, const WireType& a2,
+      const WireType& a3, const WireType& a4, const WireType& a5)  {
+    const WireType* const args[] = { &a0, &a1, &a2, &a3, &a4, &a5 };
+    return ch->Send(msg_id, args, 6);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1, const WireType& a2,
+      const WireType& a3, const WireType& a4, const WireType& a5, const WireType& a6)  {
+    const WireType* const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6 };
+    return ch->Send(msg_id, args, 7);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1, const WireType& a2,
+      const WireType& a3, const WireType& a4, const WireType& a5, const WireType& a6,
+      const WireType& a7)  {
+    const WireType* const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7 };
+    return ch->Send(msg_id, args, 8);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1, const WireType& a2,
+      const WireType& a3, const WireType& a4, const WireType& a5, const WireType& a6,
+      const WireType& a7, const WireType& a8)  {
+    const WireType* const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8 };
+    return ch->Send(msg_id, args, 9);
+  }
+
+  size_t SendMsg(int msg_id, ChannelT* ch, const WireType& a0, const WireType& a1, const WireType& a2,
+      const WireType& a3, const WireType& a4, const WireType& a5, const WireType& a6,
+      const WireType& a7, const WireType& a8, const WireType& a9)  {
+    const WireType* const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9 };
+    return ch->Send(msg_id, args, 10);
+  }
+
+  // Note: If you are adding more SendMsg() functions, update Channel::kMaxNumArgs accordingly.
+};
+
+template <bool>
+struct CompileCheck;
+
+template<>
+struct CompileCheck<true> {};
+
+
+}  // namespace ipc.
+
+#define COMPILE_CHK(expr) (ipc::CompileCheck<(expr) != 0>())
+
+// The following macros are used typically in conjuntion with The MsDispatch class.
+// They are used to define the converter class from WireType to specific types.
+// An example:
+//
+// DEFINE_IPC_MSG_CONV(5, 2) {
+//   IPC_MSG_P1(int, Int32)
+//   IPC_MSG_P2(char, Char8)
+// };
+//
+// This defines the converter class for Message id 5. It expects 2 parameters, the first one
+// is an int and the second one a char. In IPC_MSG_P1() The first parameter is the c++ type
+// and the second one is the WireType equivalent.
+// 
+// Under the covers it creates a simple tempate specialization for the generic
+// MsgParamConverter template class. From the example above, the resulting class is 
+// approximately:
+//
+//  template<>
+//  class MsgParamConverter<5> {
+//   public:
+//    enum { kNumParams = 2 };
+//    MsgParamConverter(const ipc::WireType* wt) : wt_(wt) {}
+//    int  p0() const { return wt_->RecoverInt32() }
+//    char p1() const { return wt_->RecoverChar8() }
+//  };
+//
+
+#define DEFINE_IPC_MSG_CONV(msg_id, n_params)               \
+template<>                                                  \
+class MsgParamConverter<msg_id> {                           \
+ private:                                                   \
+ const ipc::WireType* wt_;                                  \
+ public:                                                    \
+  enum { kNumParams = n_params };                           \
+  MsgParamConverter(const ipc::WireType* wt) : wt_(wt)
+
+#define IPC_MSG_P1(rt, tname)                               \
+  }                                                         \
+  rt p0() const {                                           \
+    COMPILE_CHK(1 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P2(rt, tname)                               \
+  rt p1() const {                                           \
+    COMPILE_CHK(2 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P3(rt, tname)                               \
+  rt p2() const {                                           \
+    COMPILE_CHK(3 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P4(rt, tname)                               \
+  rt p3() const {                                           \
+    COMPILE_CHK(4 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P5(rt, tname)                               \
+  rt p4() const {                                           \
+    COMPILE_CHK(5 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P6(rt, tname)                               \
+  rt p5() const {                                           \
+    COMPILE_CHK(6 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P7(rt, tname)                               \
+  rt p6() const {                                           \
+    COMPILE_CHK(7 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P8(rt, tname)                               \
+  rt p7() const {                                           \
+    COMPILE_CHK(8 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P9(rt, tname)                               \
+  rt p8() const {                                           \
+    COMPILE_CHK(9 <= kNumParams);                           \
+    return wt_->Recover##tname();                           \
+  }
+
+#define IPC_MSG_P10(rt, tname)                              \
+  rt p9() const {                                           \
+    COMPILE_CHK(10 <= kNumParams);                          \
+    return wt_->Recover##tname();                           \
+  }
+
+#endif  // SIMPLE_IPC_MSG_DISPATCH_H_

+ 12 - 0
Source/ThirdParty/SimpleIPC/ipc_pipe.h

@@ -0,0 +1,12 @@
+
+#pragma once
+
+#ifdef _MSC_VER
+
+#include "pipe_win.h"
+
+#else
+
+#include "pipe_unix.h"
+
+#endif

+ 371 - 0
Source/ThirdParty/SimpleIPC/ipc_utils.h

@@ -0,0 +1,371 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_UTLIS_H_
+#define SIMPLE_IPC_UTLIS_H_
+
+#include <string.h>
+#include <wchar.h>
+#include <new>
+
+#if !defined(countof)
+  template <typename T, size_t N>
+  char ( &_ArraySizeHelperX( T (&arr)[N] ))[N];
+  #define countof(arr) (sizeof(_ArraySizeHelperX(arr)))
+#endif
+
+#if !defined(swap)
+  template <typename T>
+  void swap(T& a, T& b) { T t(a); a = b; b = t; }
+#endif
+
+namespace memdet {
+
+template <typename T> T* new_impl(size_t n) {
+  return new T[n];
+}
+
+template <typename T> void delete_impl(T* o) {
+  delete[] o;
+}
+
+
+}  // namespace memdet
+
+namespace ipc {
+
+// The following classes are necessary because in some enviroments where this
+// library is used STL is forbidden. In particular HolderString is designed
+// to have the same functional interface as std::basic_string for the methods
+// that the ipc library uses.
+
+// This container class is an array-like which contains enough functionality
+// to replace vector<WireType> in the channel template. This is the only class
+// here that supports T to be non-pod and also T does not need a default ctor.
+template <typename T, size_t N>
+class FixedArray {
+public:
+  FixedArray() : index_(0) {}
+
+  ~FixedArray() {
+    clear();
+  }
+
+  bool push_back(const T& ob) {
+    if (index_ == N)
+      return false;
+    new(as_obj(index_)) T(ob);
+    ++index_;
+    return true;
+  }
+
+  T& operator[](size_t ix) {
+    return *as_obj(ix);
+  }
+
+  size_t max_size() const { return N; }
+
+  size_t size() const { return index_; }
+
+  void clear() {
+    for (size_t ix = 0; ix != index_; ++ix) {
+      as_obj(ix)->~T();
+    }
+    index_ = 0;
+  }
+
+private:
+  T* as_obj(size_t ix) { 
+    return reinterpret_cast<T*>(&v_[ix * sizeof(T)]);
+  }
+
+  size_t index_;
+  char v_[N * sizeof(T)];
+
+  FixedArray(const FixedArray&);
+  FixedArray& operator=(const FixedArray&);
+};
+
+
+// We don't support generic iterators but we define this magic two
+// types to support insertion to the end and erasure at the beggining.
+class IteratorEnd {};
+class IteratorBegin {};
+
+template <typename T>
+T operator+(const IteratorBegin&, T d) {
+  return d;
+}
+
+// This container is the backing store of HoldeString and a generic
+// vector of plain-old-data. Caveat: Don't use this if your PoD does
+// not have an aceptable default value of 0 as in all bytes equal to
+// zero.
+template <typename T>
+class PodVector {
+public:
+  typedef T value_type;
+
+  PodVector() : capa_(0), size_(0), buf_(0) {}
+
+  ~PodVector() {
+    clear();
+  }
+
+  const IteratorBegin begin() const { return IteratorBegin(); }
+
+  const IteratorEnd end() const { return IteratorEnd(); }
+
+  T* get() const { return buf_; }
+
+  size_t size() const { return size_; }
+
+  size_t capacity() const { return capa_; }
+
+  T& operator[](size_t ix) {
+    return buf_[ix];
+  }
+
+  const T& operator[](size_t ix) const {
+    return buf_[ix];
+  }
+
+  void clear() {
+    memdet::delete_impl(buf_);
+    size_ = 0;
+    capa_ = 0;
+    buf_ = 0;
+  }
+
+  void resize(size_t n) {
+    if (n < size_) {
+      size_ = n;
+      return;
+    }
+    Add(0, n - size_);
+  }
+
+  void reserve(size_t n) {
+    if (n <= capa_)
+      return;
+    size_t old_s = size_;
+    Add(0, n - capa_);
+    size_ = old_s;
+  }
+
+  void push_back(const T& v) {
+    Add(&v, 1);
+  }
+
+  // We only support insertions at the end so here we are
+  void insert(const IteratorEnd&, const T* begin, const T* end) {
+    size_t d = end - begin;
+    if (d > 0)
+      Add(begin, end - begin);
+  }
+
+  void erase(const IteratorBegin&, size_t n) {
+    RemoveFront(n);
+  }
+
+  // when |inp| is null then we don't copy, we just set
+  // the new memory to zeros.
+  void Add(const T* inp, size_t n) {
+    if (!n)
+      return;
+    
+    T* newb = NewAlloc(n);
+    if (newb) {
+      memcpy(newb, buf_, size_ * sizeof(T));
+      memdet::delete_impl(buf_);
+      buf_ = newb;
+    }
+    if (inp) {
+      memcpy(&buf_[size_], inp, n * sizeof(T));
+    } else {
+      memset(&buf_[size_], 0, n * sizeof(T));
+    }
+    size_ += n;
+  }
+
+  void RemoveFront(size_t n) {
+    if ((0 == size_) || (n > size_))
+      return;
+    size_t newsz = size_ - n;
+    memmove(buf_, &buf_[n], newsz);
+    size_ = newsz;
+  }
+
+  void Set(const T* inp, size_t n) {
+    size_ = 0;
+    Add(inp, n);
+  }
+
+  void Set(const PodVector<T>& other) {
+    Set(other.buf_, other.size_);
+  }
+
+  void Swap(PodVector<T>& other) {
+    swap(buf_, other.buf_);
+    swap(size_, other.size_);
+    swap(capa_, other.capa_);
+  }
+
+  void DecSize() {
+    --size_;
+  }
+  
+private:
+  T* NewAlloc(size_t n) {
+    size_t rem = capa_ - size_;
+    if (n < rem) {
+      return 0;
+    }
+    size_t new_a = n + (size_ * 2) + 1;
+    capa_ = (new_a < 16)? 16 : new_a;
+    return memdet::new_impl<T>(capa_);
+  }
+
+  PodVector(const PodVector&);
+  PodVector& operator=(const PodVector&);
+
+  size_t capa_;
+  size_t size_;
+  T* buf_;
+};
+
+// Groups common functionality to the specializations of HolderString below.
+// One trick one should be aware on this class is that leverages the fact that
+// PodVector overallocates always. So it is safe to write to str_[size_] for
+// example to null terminate.
+template <typename Ct, typename Derived>
+class StringBase {
+public:
+  typedef Ct value_type;
+
+  StringBase(const StringBase& rhs) {
+    assign(rhs.str_.get(), rhs.str_.size());
+  }
+
+  StringBase<Ct, Derived>& operator=(const StringBase<Ct, Derived>& rhs) {
+    assign(rhs.str_.get(), rhs.str_.size());
+    return *this;
+  }
+
+  void assign(const Ct* str, size_t size) {
+    str_.Set(str, size);
+    if (size)
+      str_[size] = Ct(0);
+  }
+
+  size_t size() const {
+    return str_.size();
+  }
+
+  void swap(StringBase<Ct, Derived>& other) {
+    str_.Swap(other.str_);
+  }
+
+  bool operator==(const Ct* rhs) const {
+    return (0 == static_cast<const Derived*>(this)->Compare(rhs));
+  }
+
+  bool operator!=(const Ct* rhs) const {
+    return (0 != static_cast<const Derived*>(this)->Compare(rhs));
+  }
+
+  Ct& operator[](size_t ix) {
+    return str_[ix];
+  }
+
+  const Ct& operator[](size_t ix) const {
+    return str_[ix];
+  }
+
+  size_t capacity() const { return str_.capacity(); }
+
+protected:
+  StringBase() {}
+
+  PodVector<Ct> str_;
+};
+
+template <typename Ct>
+class HolderString;
+
+// Two specializations of HolderString for char and wchar_t that
+// have enough functionality to replace (if desired) the use of the
+// standard basic_string.
+template <>
+class HolderString<char> : public StringBase<char, HolderString<char> > {
+public:
+  HolderString() {}
+
+  HolderString(const char* str) {
+    operator=(str);
+  }
+
+  void operator=(const char* str) {
+    assign(str, strlen(str));
+  }
+
+  void append(const char* str) {
+    str_.Add(str, strlen(str) + 1);
+    str_.DecSize();
+  }
+
+  const char* c_str() const {
+    if (!str_.get())
+      return "";
+    return str_.get(); 
+  }
+
+  int Compare(const char* str) const {
+    return strcmp(c_str(), str);
+  }
+  
+};
+
+template <>
+class HolderString<wchar_t> : public StringBase<wchar_t, HolderString<wchar_t> > {
+public:
+  HolderString() {}
+
+  HolderString(const wchar_t* str) {
+    operator=(str);
+  }
+
+  void operator=(const wchar_t* str) {
+    assign(str, wcslen(str));
+  }
+
+  void append(const wchar_t* str) {
+    str_.Add(str, wcslen(str) + 1);
+    str_.DecSize();
+  }
+
+  const wchar_t* c_str() const {
+    if (!str_.get())
+      return L"";
+    return str_.get(); 
+  }
+
+  int Compare(const wchar_t* str) const {
+    return wcscmp(c_str(), str);
+  }
+};
+
+}  // namespace ipc.
+
+#endif // SIMPLE_IPC_UTLIS_H_

+ 250 - 0
Source/ThirdParty/SimpleIPC/ipc_wire_types.h

@@ -0,0 +1,250 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_WIRE_TYPES_H_
+#define SIMPLE_IPC_WIRE_TYPES_H_
+
+#include "os_includes.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// This header defines the basic c++ types that can be transported via IPC.
+// The main class is WireType which both the channel and the message dispatcher know about.
+//
+
+namespace ipc {
+
+// These are the types that the IPC knows about. They are divided in four blocks. The first
+// two blocks are 'value'-like types and the second two blocks are 'array' like types.
+enum {
+  TYPE_NONE,
+  TYPE_INT32,
+  TYPE_UINT32,
+  TYPE_LONG32,
+  TYPE_ULONG32,
+  TYPE_CHAR8,
+  TYPE_CHAR16,
+  TYPE_VOIDPTR,         // void pointer (can be 32 or 64 bits).
+  TYPE_NULLSTRING8,     // like TYPE_STRING8 but its value is NULL.
+  TYPE_NULLSTRING16,    // like TYPE_STRING16 but its value is NULL.
+  TYPE_NULLBARRAY,      // like TYPE_BARRAY but its value is NULL.
+
+  TYPE_CHAR32,          // not used.
+  TYPE_INT64,           // not used.
+  TYPE_UINT64,          // not used.
+  TYPE_FLOAT32,         // not used.
+  TYPE_FLOAT64,         // not used.
+  TYPE_LONG64,          // not used.
+  TYPE_ULONG64,         // not used.
+  TYPE_NULLINT32ARRAY,  // not used.
+  TYPE_NULLUINT32ARRAY, // not used.
+  TYPE_NULLINT64ARRAY,  // not used.
+  TYPE_NULLUINT64ARRAY, // not used.
+
+  TYPE_STRING8,         // 8-bit string any encoding.
+  TYPE_STRING16,        // 16-bit string any encoding.
+  TYPE_BARRAY,          // counted byte array.
+
+  TYPE_INT32ARRAY,      // not used.
+  TYPE_UINT32ARRAY,     // not used.
+  TYPE_INT64ARRAY,      // not used.
+  TYPE_UINT64ARRAY,     // not used.
+
+  TYPE_LAST
+};
+
+// Wrapper for an array of bytes.
+struct ByteArray {
+  size_t sz_;
+  const char* buf_;
+  ByteArray(size_t sz, const char* buf) : sz_(sz), buf_(buf) {}
+};
+
+// Variant-like structure without the ownership madness.
+class MultiType {
+ public:
+  MultiType(int id) : id_(id) {}
+  int Id() const { return id_; }
+
+ protected:
+  void SetId(int id) { id_ = id; }
+
+  union {
+    int v_int;
+    unsigned int v_uint;
+    long v_long;
+    unsigned long v_ulong;
+    char v_char;
+    wchar_t v_wchar;
+    void* v_pvoid;
+  } store;
+
+  mutable IPCString store_str8;
+  mutable IPCWString store_str16;
+
+ private:
+  int id_;
+};
+
+// At its heart, WireType provides three things:
+// 1. Implicit constructors from each supported type, this is required for the template magic
+//    to work.
+// 2. Type safety; the original type is id is stored and each value will be casted via an union
+//    thus ensuring that we don't trip over c++ promotion or casting rules.
+// 3. Can distinguish between empty strings and NULL strings.
+//
+class WireType : public MultiType {
+ public:
+  // Ctors for supported types
+  WireType(int v) : MultiType(ipc::TYPE_INT32) { Set(v); }
+
+  WireType(unsigned int v) : MultiType(ipc::TYPE_UINT32) { Set(v); }
+
+  WireType(long v) : MultiType(ipc::TYPE_LONG32) { Set(v); }
+
+  WireType(unsigned long v) : MultiType(ipc::TYPE_ULONG32) { Set(v); }
+
+  WireType(char v) : MultiType(ipc::TYPE_CHAR8) { Set(v); }
+
+  WireType(wchar_t v) : MultiType(ipc::TYPE_CHAR16) { Set(v); }
+
+  WireType(const char* pc) : MultiType(ipc::TYPE_STRING8) { Set(pc); }
+
+  WireType(const wchar_t* pc) : MultiType(ipc::TYPE_STRING16) { Set(pc); }
+
+  WireType(const ByteArray& ba) : MultiType(ipc::TYPE_BARRAY) { Set(ba); }
+
+  WireType(const void* vp) : MultiType(ipc::TYPE_VOIDPTR) { Set(vp); }
+
+  ////////////////////////////////////////////////////////////////////////
+  // Getters: these are used by the sending side of the channel.
+  //
+  void* GetAsBits() const {
+    return store.v_pvoid; 
+  }
+
+  void GetString8(IPCString* out) const {
+    out->swap(store_str8);
+  }
+
+  void GetString16(IPCWString* out) const {
+    out->swap(store_str16);
+  }
+  
+  bool IsNullArray() const {
+    return (store.v_int < 0);
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Recoverers: these are used by the receiving side of the channel.
+  //
+  // These functions throw. Why you ask? well, because the type inference used
+  // elsewhere in the code requires that the error checking to be done at type
+  // conversion time and there is no way to insert a callback there.
+  // This exception does not propagate as it is catched by the callback processor.
+
+  int RecoverInt32() const {
+    if (Id() != ipc::TYPE_INT32) throw int(ipc::TYPE_INT32);
+    return store.v_int;
+  }
+
+  unsigned int RecoverUInt32() const {
+    if (Id() != ipc::TYPE_UINT32) throw int(ipc::TYPE_UINT32);
+    return store.v_uint;
+  }
+
+  unsigned int RecoverLong32() const {
+    if (Id() != ipc::TYPE_LONG32) throw int(ipc::TYPE_LONG32);
+    return store.v_long;
+  }
+
+  unsigned int RecoverULong32() const {
+    if (Id() != ipc::TYPE_ULONG32) throw int(ipc::TYPE_ULONG32);
+    return store.v_ulong;
+  }
+
+  char RecoverChar8() const {
+    if (Id() != ipc::TYPE_CHAR8) throw int(ipc::TYPE_CHAR8);
+    return store.v_char;
+  }
+
+  wchar_t RecoverChar16() const {
+    if (Id() != ipc::TYPE_CHAR16) throw int(ipc::TYPE_CHAR16);
+    return store.v_wchar;
+  }
+
+  void* RecoverVoidPtr() const {
+    if (Id() != ipc::TYPE_VOIDPTR) throw int (ipc::TYPE_VOIDPTR);
+    return store.v_pvoid;
+  }
+
+  const char* RecoverString8() const {
+    if (Id() == ipc::TYPE_STRING8) return store_str8.c_str(); 
+    else if (Id() == ipc::TYPE_NULLSTRING8) return NULL;
+    else throw int(ipc::TYPE_STRING8);
+  }
+  
+  const wchar_t* RecoverString16() const {
+    if (Id() == ipc::TYPE_STRING16) return store_str16.c_str(); 
+    else if (Id() == ipc::TYPE_NULLSTRING16) return NULL;
+    else throw int(ipc::TYPE_STRING16);
+  }
+
+  const ByteArray RecoverByteArray() const {
+    if (Id() == ipc::TYPE_BARRAY) return ByteArray(store_str8.size(), store_str8.c_str());
+    else if (Id() == ipc::TYPE_NULLBARRAY) return ByteArray(0, NULL);
+    else throw int(ipc::TYPE_BARRAY);
+  }
+
+ private:
+  void Set(int v) { store.v_int = v; }
+  void Set(unsigned int v) { store.v_uint = v; }
+  void Set(long v) { store.v_long = v; }
+  void Set(unsigned long v) { store.v_ulong = v; }
+  void Set(char v) { store.v_int = 0; store.v_char = v; }
+  void Set(wchar_t v) { store.v_int = 0; store.v_wchar = v; }
+  void Set(const void* v) { store.v_pvoid = const_cast<void*>(v); }
+  
+  void Set(const char* pc) { 
+    if (!pc) {
+      store.v_int = -1;
+      SetId(TYPE_NULLSTRING8);
+      return;
+    }
+    store_str8 = pc;
+  }
+
+  void Set(const wchar_t* pc) {
+    if (!pc) {
+      store.v_int = -1;
+      SetId(TYPE_NULLSTRING16);
+      return;
+    }
+    store_str16 = pc;
+  }
+
+  void Set(const ByteArray& ba) {
+    if (!ba.buf_) {
+      store.v_int = -1;
+      SetId(TYPE_NULLBARRAY);
+      return;
+    }
+    store_str8.assign(ba.buf_, ba.sz_);
+  }
+
+};
+
+}  // namespace ipc.
+
+#endif  // SIMPLE_IPC_WIRE_TYPES_H_
+

+ 53 - 0
Source/ThirdParty/SimpleIPC/os_includes.h

@@ -0,0 +1,53 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_OS_INCLUDES_H_
+#define SIMPLE_IPC_OS_INCLUDES_H_
+
+#if defined(WIN32)
+//////////////////////////////// Windows //////////////////////////////////////////////////////////
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500     
+#endif
+
+#include <windows.h>
+
+#else
+//////////////////////////////// Other OS /////////////////////////////////////////////////////////
+#include <stdlib.h>
+
+#endif  // defined(WIN32)
+
+//////////////////////////////// Every OS /////////////////////////////////////////////////////////
+//#define IPC_USE_STL
+
+#if defined(IPC_USE_STL)
+  #include <string>
+  #include <vector>
+  typedef std::string IPCString;
+  typedef std::wstring IPCWString;
+  typedef std::vector<char> IPCCharVector;
+  typedef std::vector<void*> IPCVoidPtrVector;
+  typedef std::vector<int> IPCIntVector;
+#else
+  #include "ipc_utils.h"
+  typedef ipc::HolderString<char> IPCString;
+  typedef ipc::HolderString<wchar_t> IPCWString;
+  typedef ipc::PodVector<char> IPCCharVector;
+  typedef ipc::PodVector<void*> IPCVoidPtrVector;
+  typedef ipc::PodVector<int> IPCIntVector;
+#endif
+
+
+#endif  // SIMPLE_IPC_OS_INCLUDES_H_

+ 127 - 0
Source/ThirdParty/SimpleIPC/pipe_unix.cpp

@@ -0,0 +1,127 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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.
+
+#include "pipe_unix.h"
+
+#include <sys/socket.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define HANDLE_EINTR(x) ({ \
+typeof(x) __eintr_result__; \
+do { \
+__eintr_result__ = x; \
+} while (__eintr_result__ == -1 && errno == EINTR); \
+__eintr_result__;\
+})
+
+
+namespace  {
+
+bool SilenceSocket(int fd) {
+  int nosigpipe = 1;
+  // On OSX an attempt to read or write to a closed socket may generate a
+  // SIGPIPE rather than returning -1.  setsockopt will shut this off.
+  if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE,
+                      &nosigpipe, sizeof nosigpipe)) {
+    return false;
+  }
+  return true;
+}
+
+size_t ReadFromFD(int fd, char* buffer, size_t bytes) {
+  ssize_t bytes_read =
+  HANDLE_EINTR(read(fd, buffer, bytes));
+  if (bytes_read < 0) {
+    return -1;
+  }
+  return bytes_read;
+}
+
+size_t WriteToFD(int fd, const char* data, size_t size) {
+  // Allow for partial writes.
+  ssize_t written_total = 0;
+  for (ssize_t written_partial = 0; written_total < size; written_total += written_partial) {
+    written_partial =
+    HANDLE_EINTR(write(fd, data + written_total, size - written_total));
+    if (written_partial < 0) {
+      return -1;
+    }
+  }
+  return written_total;
+}
+
+}  // namespace
+
+
+PipePair::PipePair() {
+  fd_[0] = -1;
+  fd_[1] = -1;
+  
+  if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd_) !=0) {
+    return;
+  }
+};
+
+PipeUnix::PipeUnix() : fd_(-1) {
+}
+
+bool PipeUnix::OpenClient(int fd) {
+  if (!SilenceSocket(fd)) {
+    return false;
+  }
+  fd_ = fd;
+  return true;
+}
+
+bool PipeUnix::OpenServer(int fd) {
+  if (!SilenceSocket(fd)) {
+    return false;
+  }  
+  fd_ = fd;
+  return true;
+}
+
+
+bool PipeUnix::Write(const void* buf, size_t sz) {
+  if (sz == -1) {
+    return false;
+  }
+  size_t written = WriteToFD(fd_, static_cast<const char*> (buf), sz);
+  return (sz == written);
+}
+
+bool PipeUnix::Read(void* buf, size_t* sz) {
+  size_t read = ReadFromFD(fd_, static_cast<char*> (buf), *sz);
+  if (read == -1) {
+    return false;
+  }
+  *sz = read;
+  return true;
+}
+
+
+char* PipeTransport::Receive(size_t* size) {
+  if (buf_.size() < kBufferSz) {
+    buf_.resize(kBufferSz);
+  }
+  
+  *size = kBufferSz;
+  if (!Read(&buf_[0], size)) {
+    return NULL;
+  }
+  return &buf_[0];
+}
+
+

+ 66 - 0
Source/ThirdParty/SimpleIPC/pipe_unix.h

@@ -0,0 +1,66 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_PIPE_UNIX_H_
+#define SIMPLE_IPC_PIPE_UNIX_H_
+
+
+#include "os_includes.h"
+#include "ipc_constants.h"
+
+class PipePair {
+public:
+  PipePair();
+  
+  int fd1() const { return fd_[0]; }
+  int fd2() const { return fd_[1]; }
+  
+private:
+  int fd_[2];
+};
+
+
+class PipeUnix {
+public:
+  PipeUnix();
+
+  bool OpenClient(int fd);
+  bool OpenServer(int fd);
+
+  bool Write(const void* buf, size_t sz);
+  bool Read(void* buf, size_t* sz);
+
+  bool IsConnected() const { return fd_ != -1; }
+
+private:
+  int fd_;
+};
+
+
+class PipeTransport : public PipeUnix {
+public:
+  static const size_t kBufferSz = 4096;
+  
+  size_t Send(const void* buf, size_t sz) {
+    return Write(buf, sz) ? ipc::RcOK : ipc::RcErrTransportWrite;
+  }
+  
+  char* Receive(size_t* size);
+
+private:
+  IPCCharVector buf_;
+};
+
+
+#endif  // SIMPLE_IPC_PIPE_UNIX_H_

+ 157 - 0
Source/ThirdParty/SimpleIPC/pipe_win.cpp

@@ -0,0 +1,157 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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.
+
+#include "pipe_win.h"
+#include <Sddl.h>
+#include <AccCtrl.h>
+#include <Aclapi.h>
+
+namespace {
+const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\";
+const int kPipeBufferSz = 4 * 1024;
+}  // namespace
+
+bool checkIntegritySupport() {
+  OSVERSIONINFO osvi;
+
+  ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+  GetVersionEx(&osvi);
+
+  return osvi.dwMajorVersion > 5;
+}
+
+LONG g_pipe_seq = 0;
+
+HANDLE PipePair::OpenPipeServer(const wchar_t* name, bool low_integrity) {
+  SECURITY_ATTRIBUTES sa = {0};
+  SECURITY_ATTRIBUTES *psa = 0;
+
+  static const bool is_integrity_supported = checkIntegritySupport();
+
+  if (is_integrity_supported && low_integrity) {
+    psa = &sa;
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.bInheritHandle = TRUE;
+    if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
+        TEXT("S:(ML;;NWNR;;;LW)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL)) 
+      return INVALID_HANDLE_VALUE;
+  }
+
+  IPCWString pipename(kPipePrefix);
+  pipename.append(name);
+  return ::CreateNamedPipeW(pipename.c_str(), PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
+                            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
+                            1, kPipeBufferSz, kPipeBufferSz, 200, psa);
+}
+
+HANDLE PipePair::OpenPipeClient(const wchar_t* name, bool inherit, bool impersonate) {
+  IPCWString pipename(kPipePrefix);
+  pipename.append(name);
+
+  SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, inherit ? TRUE : FALSE};
+  for (;;) {
+    DWORD attributes = impersonate ? 0 : SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION;
+    HANDLE pipe = ::CreateFileW(pipename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa,
+                                OPEN_EXISTING, attributes, NULL);
+    if (INVALID_HANDLE_VALUE == pipe) {
+      if (ERROR_PIPE_BUSY != ::GetLastError()) {
+        return pipe;
+      }
+      // wait and retry.
+      ::Sleep(25);
+    } else {
+      // success.
+      return pipe;
+    }
+  }
+}
+
+
+PipePair::PipePair(bool inherit_fd2) : srv_(NULL), cln_(NULL) {
+  // Come up with a reasonable unique name.
+  const wchar_t kPipePattern[] = L"ko.%x.%x.%x";
+  wchar_t name[8*3 + sizeof(kPipePattern)];
+  ::wsprintfW(name, kPipePattern, ::GetCurrentProcessId(), ::GetTickCount(), 
+              ::InterlockedIncrement(&g_pipe_seq));
+  HANDLE server = OpenPipeServer(name);
+  if (INVALID_HANDLE_VALUE == server) {
+    return;
+  }
+  // Don't allow client impersonation.
+  HANDLE client = OpenPipeClient(name, inherit_fd2, false);
+  if (INVALID_HANDLE_VALUE == client) {
+    ::CloseHandle(server);
+    return;
+  }
+  if (!::ConnectNamedPipe(server, NULL)) {
+    if (ERROR_PIPE_CONNECTED != ::GetLastError()) {
+      ::CloseHandle(server);
+      ::CloseHandle(client);
+    return;
+    }
+  }
+
+  srv_ = server;
+  cln_ = client;
+}
+
+
+PipeWin::PipeWin() : pipe_(INVALID_HANDLE_VALUE) {
+}
+
+PipeWin::~PipeWin() {
+  if (pipe_ != INVALID_HANDLE_VALUE) {
+    ::DisconnectNamedPipe(pipe_);  // $$$ disconect is valid on the server side.
+    ::CloseHandle(pipe_);
+  }
+}
+
+bool PipeWin::OpenClient(HANDLE pipe) {
+  pipe_ = pipe;  
+  return true;
+}
+
+bool PipeWin::OpenServer(HANDLE pipe, bool connect) {
+  pipe_ = pipe;
+
+  if (connect) {
+    if (!::ConnectNamedPipe(pipe, NULL)) {
+      if (ERROR_PIPE_CONNECTED != ::GetLastError()) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool PipeWin::Write(const void* buf, size_t sz) {
+  DWORD written = 0;
+  return (TRUE == ::WriteFile(pipe_, buf, sz, &written, NULL));
+}
+
+bool PipeWin::Read(void* buf, size_t* sz) {
+  return (TRUE == ::ReadFile(pipe_, buf, *sz, reinterpret_cast<DWORD*>(sz), NULL));
+}
+
+
+char* PipeTransport::Receive(size_t* size) {
+  if (buf_.size() < kBufferSz)
+    buf_.resize(kBufferSz);
+
+  *size = kBufferSz;
+  if (!Read(&buf_[0], size))
+    return NULL;
+  return &buf_[0];
+}

+ 67 - 0
Source/ThirdParty/SimpleIPC/pipe_win.h

@@ -0,0 +1,67 @@
+// Copyright (c) 2010 Google Inc.
+//
+// Licensed 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 SIMPLE_IPC_PIPE_WIN_H_
+#define SIMPLE_IPC_PIPE_WIN_H_
+
+#include "os_includes.h"
+#include "ipc_constants.h"
+
+class PipePair {
+public:
+  PipePair(bool inherit_fd2 = false);
+  HANDLE fd1() const { return srv_; }
+  HANDLE fd2() const { return cln_; }
+
+  static HANDLE OpenPipeServer(const wchar_t* name, bool low_integrity = true);
+  static HANDLE OpenPipeClient(const wchar_t* name, bool inherit, bool impersonate);
+
+private:
+  HANDLE srv_;
+  HANDLE cln_;
+};
+
+class PipeWin {
+public:
+  PipeWin();
+  ~PipeWin();
+
+  bool OpenClient(HANDLE pipe);
+  bool OpenServer(HANDLE pipe, bool connect = false);
+
+  bool Write(const void* buf, size_t sz);
+  bool Read(void* buf, size_t* sz);
+
+  bool IsConnected() const { return INVALID_HANDLE_VALUE != pipe_; }
+
+private:
+  HANDLE pipe_;
+};
+
+
+class PipeTransport : public PipeWin {
+public:
+  static const size_t kBufferSz = 4096;
+
+  size_t Send(const void* buf, size_t sz) {
+    return Write(buf, sz) ? ipc::RcOK : ipc::RcErrTransportWrite;
+  }
+
+  char* Receive(size_t* size);
+
+private:
+  IPCCharVector buf_;
+};
+
+#endif  // SIMPLE_IPC_PIPE_WIN_H_