Merge pull request #514 from charliemblack/develop

Update the build instructions for Mac
diff --git a/cppcache/integration/framework/Cluster.cpp b/cppcache/integration/framework/Cluster.cpp
index f0907e1..964dfeb 100644
--- a/cppcache/integration/framework/Cluster.cpp
+++ b/cppcache/integration/framework/Cluster.cpp
@@ -45,6 +45,7 @@
       .withHttpServicePort(0)
       .withClasspath(cluster_.getClasspath())
       .withSecurityManager(cluster_.getSecurityManager())
+      .withPreferIPv6(cluster_.getUseIPv6())
       .execute(cluster_.getUser(), cluster_.getPassword());
 
   started_ = true;
@@ -76,6 +77,7 @@
       .withUser(cluster_.getUser())
       .withPassword(cluster_.getPassword())
       .withCacheXMLFile(getCacheXMLFile())
+      .withPreferIPv6(cluster_.getUseIPv6())
       .execute();
 
 //  std::cout << "server: " << serverAddress_.port << ": started" << std::endl << std::flush;
@@ -95,7 +97,7 @@
   for (size_t i = 0; i < initialLocators_; i++) {
     locators_.push_back({*this, locators_,
                          name_ + "/locator/" + std::to_string(i),
-                         jmxManagerPort_});
+                         jmxManagerPort_, getUseIPv6()});
   }
 
   servers_.reserve(initialServers_);
@@ -106,7 +108,7 @@
                cacheXMLFiles_[i];
 
     servers_.push_back(
-      {*this, locators_, name_ + "/server/" + std::to_string(i), xmlFile});
+      {*this, locators_, name_ + "/server/" + std::to_string(i), xmlFile, getUseIPv6()});
   }
 
   startLocators();
diff --git a/cppcache/integration/framework/Cluster.h b/cppcache/integration/framework/Cluster.h
index 4578437..cb2be5f 100644
--- a/cppcache/integration/framework/Cluster.h
+++ b/cppcache/integration/framework/Cluster.h
@@ -41,12 +41,16 @@
 class Locator {
  public:
   Locator(Cluster &cluster, std::vector<Locator> &locators, std::string name,
-          uint16_t jmxManagerPort)
+          uint16_t jmxManagerPort, bool useIPv6)
       : cluster_(cluster),
         name_(std::move(name)),
         locators_(locators),
         jmxManagerPort_(jmxManagerPort) {
     auto hostname = "localhost";
+    if (useIPv6) {
+      hostname = "ip6-localhost";
+    }
+
     auto port = Framework::getAvailablePort();
 
     locatorAddress_ = LocatorAddress{hostname, port};
@@ -103,12 +107,18 @@
 
 class Server {
  public:
-  Server(Cluster &cluster, std::vector<Locator> &locators, std::string name, std::string xmlFile)
+  Server(Cluster &cluster, std::vector<Locator> &locators, std::string name,
+         std::string xmlFile, bool useIPv6)
       : cluster_(cluster),
         locators_(locators),
         name_(std::move(name)),
         xmlFile_(xmlFile) {
+
     auto hostname = "localhost";
+    if (useIPv6) {
+      hostname = "ip6-localhost";
+    }
+
     auto port = static_cast<uint16_t>(0);
     serverAddress_ = ServerAddress{hostname, port};
 
@@ -164,9 +174,21 @@
 using Password = NamedType<std::string, struct PasswordParameter>;
 using CacheXMLFiles =
     NamedType<std::vector<std::string>, struct CacheXMLFilesParameter>;
+using UseIpv6 = NamedType<bool, struct UseIpv6Parameter>;
 
 class Cluster {
  public:
+  Cluster(LocatorCount initialLocators, ServerCount initialServers,
+          UseIpv6 useIPv6)
+      : Cluster(Name(std::string(::testing::UnitTest::GetInstance()
+                                     ->current_test_info()
+                                     ->test_case_name()) +
+                     "/" +
+                     ::testing::UnitTest::GetInstance()
+                         ->current_test_info()
+                         ->name()),
+                initialLocators, initialServers, useIPv6) {}
+
   Cluster(LocatorCount initialLocators, ServerCount initialServers)
       : Cluster(Name(std::string(::testing::UnitTest::GetInstance()
                                      ->current_test_info()
@@ -177,6 +199,7 @@
                          ->name()),
                 initialLocators, initialServers) {}
 
+
   Cluster(LocatorCount initialLocators, ServerCount initialServers,
           CacheXMLFiles cacheXMLFiles)
       : name_(std::string(::testing::UnitTest::GetInstance()
@@ -191,14 +214,20 @@
     cacheXMLFiles_ = cacheXMLFiles.get();
   }
 
+  Cluster(Name name, LocatorCount initialLocators, ServerCount initialServers,
+          UseIpv6 useIPv6)
+      : Cluster(Name(name.get()), Classpath(""), SecurityManager(""), User(""),
+                Password(""), initialLocators, initialServers,
+                CacheXMLFiles({}), useIPv6) {}
+
   Cluster(Name name, LocatorCount initialLocators, ServerCount initialServers)
       : Cluster(Name(name.get()), Classpath(""), SecurityManager(""), User(""),
                 Password(""), initialLocators, initialServers,
-                CacheXMLFiles({})) {}
+                CacheXMLFiles({}), UseIpv6(false)) {}
 
   Cluster(Name name, Classpath classpath, SecurityManager securityManager,
           User user, Password password, LocatorCount initialLocators,
-          ServerCount initialServers, CacheXMLFiles cacheXMLFiles)
+          ServerCount initialServers, CacheXMLFiles cacheXMLFiles, UseIpv6 useIPv6)
       : name_(name.get()),
         classpath_(classpath.get()),
         securityManager_(securityManager.get()),
@@ -208,6 +237,7 @@
         initialServers_(initialServers.get()) {
     jmxManagerPort_ = Framework::getAvailablePort();
     cacheXMLFiles_ = cacheXMLFiles.get();
+    useIPv6_ = useIPv6.get();
 
     removeServerDirectory();
     start();
@@ -311,6 +341,8 @@
 
   std::vector<std::string> &getCacheXMLFiles() { return cacheXMLFiles_; }
 
+  bool getUseIPv6() { return useIPv6_; }
+
  private:
   std::string name_;
   std::string classpath_;
@@ -328,6 +360,8 @@
   bool started_ = false;
   uint16_t jmxManagerPort_;
 
+  bool useIPv6_ = false;
+
   GfshExecute gfsh_;
 
   void startLocators();
diff --git a/cppcache/integration/framework/Gfsh.h b/cppcache/integration/framework/Gfsh.h
index 7df7ebd..e2754bc 100644
--- a/cppcache/integration/framework/Gfsh.h
+++ b/cppcache/integration/framework/Gfsh.h
@@ -141,6 +141,13 @@
         command_ += " --connect=" + connect;
         return *this;
       };
+
+      Locator &withPreferIPv6(bool useIPv6) {
+        if (useIPv6) {
+          command_ += " --J=-Djava.net.preferIPv6Addresses=true";
+        }
+        return *this;
+      };
     };
 
     class Server : public Command<void> {
@@ -217,6 +224,13 @@
         }
         return *this;
       }
+
+      Server &withPreferIPv6(bool useIPv6) {
+        if (useIPv6) {
+          command_ += " --J=-Djava.net.preferIPv6Addresses=true";
+        }
+        return *this;
+      };
     };
 
    private:
diff --git a/cppcache/integration/test/BasicIPv6Test.cpp b/cppcache/integration/test/BasicIPv6Test.cpp
new file mode 100644
index 0000000..15ff191
--- /dev/null
+++ b/cppcache/integration/test/BasicIPv6Test.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#include <framework/Cluster.h>
+#include <framework/Framework.h>
+#include <framework/Gfsh.h>
+#include <hacks/range.h>
+
+#include <iostream>
+#include <unordered_map>
+
+#include <gtest/gtest.h>
+
+#include <geode/Cache.hpp>
+#include <geode/PoolManager.hpp>
+#include <geode/QueryService.hpp>
+#include <geode/RegionFactory.hpp>
+#include <geode/RegionShortcut.hpp>
+#include <geode/Struct.hpp>
+
+namespace {
+
+using apache::geode::client::Cache;
+using apache::geode::client::CacheableInt32;
+using apache::geode::client::CacheableString;
+using apache::geode::client::Region;
+using apache::geode::client::RegionShortcut;
+using apache::geode::client::Struct;
+
+std::shared_ptr<Region> setupRegion(Cache& cache) {
+  auto region = cache.createRegionFactory(RegionShortcut::PROXY)
+                    .setPoolName("default")
+                    .create("region");
+
+  return region;
+}
+
+/**
+ * Example test using 2 servers and waiting for async tasks to synchronize using
+ * furtures.
+ */
+TEST(BasicIPv6Test, queryResultForRange) {
+  Cluster cluster{LocatorCount{1}, ServerCount{1}, UseIpv6(true)};
+  cluster.getGfsh()
+      .create()
+      .region()
+      .withName("region")
+      .withType("REPLICATE")
+      .execute();
+
+  auto cache = cluster.createCache();
+  auto region = setupRegion(cache);
+
+  std::unordered_map<int, std::string> values = {
+      {1, "one"}, {2, "two"}, {3, "three"}};
+
+  for (auto&& value : values) {
+    region->put(value.first, value.second);
+  }
+
+  auto&& queryResult =
+      cache.getQueryService()
+          ->newQuery("SELECT e.key, e.value FROM /region.entries e")
+          ->execute();
+  EXPECT_EQ(3, queryResult->size());
+
+  for (auto&& row : hacks::range(*queryResult)) {
+    auto rowStruct = std::dynamic_pointer_cast<Struct>(row);
+    ASSERT_NE(nullptr, rowStruct);
+    EXPECT_EQ(2, rowStruct->size());
+
+    auto key = -1;
+    for (auto&& column : *rowStruct) {
+      // Expect to read: key:int, value:string
+      if (auto columnValue =
+              std::dynamic_pointer_cast<CacheableInt32>(column)) {
+        key = columnValue->value();
+        EXPECT_NE(values.end(), values.find(key));
+      } else if (auto columnValue =
+                     std::dynamic_pointer_cast<CacheableString>(column)) {
+        auto value = columnValue->value();
+        EXPECT_EQ(values.find(key)->second, value);
+      } else {
+        FAIL() << "Column is not int or string.";
+      }
+    }
+  }
+}
+
+}  // namespace
diff --git a/cppcache/integration/test/CMakeLists.txt b/cppcache/integration/test/CMakeLists.txt
index a1d1134..21f1390 100644
--- a/cppcache/integration/test/CMakeLists.txt
+++ b/cppcache/integration/test/CMakeLists.txt
@@ -36,6 +36,7 @@
   StructTest.cpp
   TransactionCleaningTest.cpp
   CleanIdleConnections.cpp
+  BasicIPv6Test.cpp
 )
 
 target_compile_definitions(cpp-integration-test
diff --git a/cppcache/src/ClientProxyMembershipID.cpp b/cppcache/src/ClientProxyMembershipID.cpp
index 8a0ee62..81e4d0b 100644
--- a/cppcache/src/ClientProxyMembershipID.cpp
+++ b/cppcache/src/ClientProxyMembershipID.cpp
@@ -30,7 +30,6 @@
 #include "DistributedSystem.hpp"
 #include "Version.hpp"
 
-#define ADDRSIZE 4
 #define DCPORT 12334
 #define VMKIND 13
 #define ROLEARRLENGTH 0
@@ -45,40 +44,62 @@
 const int8_t ClientProxyMembershipID::TOKEN_ORDINAL = -1;
 
 ClientProxyMembershipID::ClientProxyMembershipID()
-    : m_hostPort(0),
-      m_hostAddr(nullptr),
-      m_hostAddrLen(0),
-      m_hostAddrLocalMem(false),
-      m_vmViewId(0) {}
+    : m_hostPort(0), m_vmViewId(0) {}
 
-ClientProxyMembershipID::~ClientProxyMembershipID() noexcept {
-  if (m_hostAddrLocalMem) delete[] m_hostAddr;
-}
+ClientProxyMembershipID::~ClientProxyMembershipID() noexcept {}
 
 ClientProxyMembershipID::ClientProxyMembershipID(
     std::string dsName, std::string randString, const char* hostname,
-    uint32_t hostAddr, uint32_t hostPort, const char* durableClientId,
-    const std::chrono::seconds durableClntTimeOut)
-    : m_hostAddrAsUInt32(hostAddr) {
+    const ACE_INET_Addr& address, uint32_t hostPort,
+    const char* durableClientId,
+    const std::chrono::seconds durableClntTimeOut) {
   auto vmPID = boost::this_process::get_id();
-  initObjectVars(hostname, reinterpret_cast<uint8_t*>(&m_hostAddrAsUInt32), 4,
-                 false, hostPort, durableClientId, durableClntTimeOut, DCPORT,
-                 vmPID, VMKIND, 0, dsName.c_str(), randString.c_str(), 0);
+
+  initHostAddressVector(address);
+
+  initObjectVars(hostname, hostPort, durableClientId, durableClntTimeOut,
+                 DCPORT, vmPID, VMKIND, 0, dsName.c_str(), randString.c_str(),
+                 0);
 }
 
 // This is only for unit tests and should not be used for any other purpose. See
-// testEntriesMapForVersioning.cpp for more details
+// ClientProxyMembershipIDTest.cpp for more details
 ClientProxyMembershipID::ClientProxyMembershipID(
-    uint8_t* hostAddr, uint32_t hostAddrLen, uint32_t hostPort,
+    const uint8_t* hostAddr, uint32_t hostAddrLen, uint32_t hostPort,
     const char* dsname, const char* uniqueTag, uint32_t vmViewId) {
   auto vmPID = boost::this_process::get_id();
-  initObjectVars("localhost", hostAddr, hostAddrLen, false, hostPort, "",
-                 std::chrono::seconds::zero(), DCPORT, vmPID, VMKIND, 0, dsname,
-                 uniqueTag, vmViewId);
+
+  initHostAddressVector(hostAddr, hostAddrLen);
+
+  initObjectVars("localhost", hostPort, "", std::chrono::seconds::zero(),
+                 DCPORT, vmPID, VMKIND, 0, dsname, uniqueTag, vmViewId);
 }
+
+void ClientProxyMembershipID::initHostAddressVector(
+    const ACE_INET_Addr& address) {
+  int len;
+  if (address.get_type() == AF_INET6) {
+    const struct sockaddr_in6* sa6 =
+        static_cast<const struct sockaddr_in6*>(address.get_addr());
+    auto saddr = reinterpret_cast<const uint8_t*>(&sa6->sin6_addr);
+    len = sizeof(sa6->sin6_addr);
+    m_hostAddr.assign(saddr, saddr + len);
+  } else {
+    const struct sockaddr_in* sa4 =
+        static_cast<const struct sockaddr_in*>(address.get_addr());
+    auto ipaddr = reinterpret_cast<const uint8_t*>(&sa4->sin_addr);
+    len = sizeof(sa4->sin_addr);
+    m_hostAddr.assign(ipaddr, ipaddr + len);
+  }
+}
+
+void ClientProxyMembershipID::initHostAddressVector(const uint8_t* hostAddr,
+                                                    uint32_t hostAddrLen) {
+  m_hostAddr.assign(hostAddr, hostAddr + hostAddrLen);
+}
+
 void ClientProxyMembershipID::initObjectVars(
-    const char* hostname, uint8_t* hostAddr, uint32_t hostAddrLen,
-    bool hostAddrLocalMem, uint32_t hostPort, const char* durableClientId,
+    const char* hostname, uint32_t hostPort, const char* durableClientId,
     const std::chrono::seconds durableClntTimeOut, int32_t dcPort, int32_t vPID,
     int8_t vmkind, int8_t splitBrainFlag, const char* dsname,
     const char* uniqueTag, uint32_t vmViewId) {
@@ -89,9 +110,6 @@
     m_dsname = std::string(dsname);
   }
   m_hostPort = hostPort;
-  m_hostAddr = hostAddr;
-  m_hostAddrLen = hostAddrLen;
-  m_hostAddrLocalMem = hostAddrLocalMem;
   if (uniqueTag == nullptr) {
     m_uniqueTag = std::string("");
   } else {
@@ -101,12 +119,8 @@
   m_vmViewId = vmViewId;
   m_memID.write(static_cast<int8_t>(DSCode::FixedIDByte));
   m_memID.write(static_cast<int8_t>(DSCode::InternalDistributedMember));
-  m_memID.writeArrayLen(ADDRSIZE);
-  // writing first 4 bytes of the address. This will be same until
-  // IPV6 support is added in the client
-  uint32_t temp;
-  memcpy(&temp, hostAddr, 4);
-  m_memID.writeInt(static_cast<int32_t>(temp));
+  m_memID.writeBytes(m_hostAddr.data(),
+                     static_cast<int32_t>(m_hostAddr.size()));
   // m_memID.writeInt((int32_t)hostPort);
   m_memID.writeInt(static_cast<int32_t>(synch_counter));
   m_memID.writeString(hostname);
@@ -162,10 +176,12 @@
   }
   LOGDEBUG("GethashKey %s client id: %s ", m_hashKey.c_str(), clientID.c_str());
 }
+
 const char* ClientProxyMembershipID::getDSMemberId(uint32_t& mesgLength) const {
   mesgLength = static_cast<int32_t>(m_memIDStr.size());
   return m_memIDStr.c_str();
 }
+
 const char* ClientProxyMembershipID::getDSMemberIdForCS43(
     uint32_t& mesgLength) const {
   mesgLength = static_cast<int32_t>(m_dsmemIDStr.size());
@@ -186,7 +202,6 @@
   // deserialization for PR FX HA
 
   auto len = input.readArrayLength();  // inetaddress len
-  m_hostAddrLocalMem = true;
   auto hostAddr = new uint8_t[len];
   input.readBytesOnly(hostAddr, len);  // inetaddress
   auto hostPort = input.readInt32();   // port
@@ -208,20 +223,22 @@
   int32_t vmViewId = 0;
   readVersion(splitbrain, input);
 
+  initHostAddressVector(hostAddr, len);
+
   if (vmKind != ClientProxyMembershipID::LONER_DM_TYPE) {
     vmViewId = std::stoi(uniqueTag->value());
-    initObjectVars(hostname->value().c_str(), hostAddr, len, true, hostPort,
+    initObjectVars(hostname->value().c_str(), hostPort,
                    durableClientId->value().c_str(), durableClntTimeOut, dcport,
                    vPID, vmKind, splitbrain, dsName->value().c_str(), nullptr,
                    vmViewId);
   } else {
     // initialize the object
-    initObjectVars(hostname->value().c_str(), hostAddr, len, true, hostPort,
+    initObjectVars(hostname->value().c_str(), hostPort,
                    durableClientId->value().c_str(), durableClntTimeOut, dcport,
                    vPID, vmKind, splitbrain, dsName->value().c_str(),
                    uniqueTag->value().c_str(), 0);
   }
-
+  delete[] hostAddr;
   readAdditionalData(input);
 }
 
@@ -231,16 +248,12 @@
   std::shared_ptr<CacheableString> hostname, dsName, uniqueTag, vmViewIdstr;
 
   len = input.readArrayLength();  // inetaddress len
-  m_hostAddrLocalMem = true;
   /* adongre - Coverity II
    * CID 29183: Out-of-bounds access (OVERRUN_DYNAMIC)
    */
-  // hostAddr = new uint8_t(len);
   hostAddr = new uint8_t[len];
-
   input.readBytesOnly(hostAddr, len);  // inetaddress
-
-  hostPort = input.readInt32();  // port
+  hostPort = input.readInt32();        // port
   // TODO: RVV get the host name from
 
   // read and ignore flag
@@ -258,19 +271,20 @@
 
   dsName = std::dynamic_pointer_cast<CacheableString>(input.readObject());
 
+  initHostAddressVector(hostAddr, len);
+
   if (vmKind != ClientProxyMembershipID::LONER_DM_TYPE) {
     // initialize the object with the values read and some dummy values
-    initObjectVars("", hostAddr, len, true, hostPort, "",
-                   std::chrono::seconds::zero(), DCPORT, 0, vmKind, 0,
-                   dsName->value().c_str(), nullptr, vmViewId);
+    initObjectVars("", hostPort, "", std::chrono::seconds::zero(), DCPORT, 0,
+                   vmKind, 0, dsName->value().c_str(), nullptr, vmViewId);
   } else {
     // initialize the object with the values read and some dummy values
-    initObjectVars("", hostAddr, len, true, hostPort, "",
-                   std::chrono::seconds::zero(), DCPORT, 0, vmKind, 0,
-                   dsName->value().c_str(), uniqueTag->value().c_str(),
-                   vmViewId);
+    initObjectVars("", hostPort, "", std::chrono::seconds::zero(), DCPORT, 0,
+                   vmKind, 0, dsName->value().c_str(),
+                   uniqueTag->value().c_str(), vmViewId);
   }
 
+  delete[] hostAddr;
   readAdditionalData(input);
 
   return this;
@@ -300,10 +314,10 @@
   if (myPort < otherPort) return -1;
   if (myPort > otherPort) return 1;
 
-  uint8_t* myAddr = getHostAddr();
-  uint8_t* otherAddr = otherMember.getHostAddr();
-  // Discard null cases
-  if (myAddr == nullptr && otherAddr == nullptr) {
+  auto myAddr = getHostAddr();
+  auto otherAddr = otherMember.getHostAddr();
+
+  if (myAddr.size() == 0 && otherAddr.size() == 0) {
     if (myPort < otherPort) {
       return -1;
     } else if (myPort > otherPort) {
@@ -311,9 +325,9 @@
     } else {
       return 0;
     }
-  } else if (myAddr == nullptr) {
+  } else if (myAddr.size() == 0) {
     return -1;
-  } else if (otherAddr == nullptr) {
+  } else if (otherAddr.size() == 0) {
     return 1;
   }
   for (uint32_t i = 0; i < getHostAddrLen(); i++) {
diff --git a/cppcache/src/ClientProxyMembershipID.hpp b/cppcache/src/ClientProxyMembershipID.hpp
index 6d9a659..2f95ef7 100644
--- a/cppcache/src/ClientProxyMembershipID.hpp
+++ b/cppcache/src/ClientProxyMembershipID.hpp
@@ -21,6 +21,9 @@
 #define GEODE_CLIENTPROXYMEMBERSHIPID_H_
 
 #include <string>
+#include <vector>
+
+#include <ace/INET_Addr.h>
 
 #include <geode/DataOutput.hpp>
 #include <geode/internal/functional.hpp>
@@ -42,7 +45,7 @@
   const char* getDSMemberIdForCS43(uint32_t& mesgLength) const;
 
   ClientProxyMembershipID(std::string dsName, std::string randString,
-                          const char* hostname, uint32_t hostAddr,
+                          const char* hostname, const ACE_INET_Addr& address,
                           uint32_t hostPort,
                           const char* durableClientId = nullptr,
                           const std::chrono::seconds durableClntTimeOut =
@@ -50,7 +53,7 @@
 
   // This constructor is only for testing and should not be used for any
   // other purpose. See testEntriesMapForVersioning.cpp for more details
-  ClientProxyMembershipID(uint8_t* hostAddr, uint32_t hostAddrLen,
+  ClientProxyMembershipID(const uint8_t* hostAddr, uint32_t hostAddrLen,
                           uint32_t hostPort, const char* dsname,
                           const char* uniqueTag, uint32_t vmViewId);
   // ClientProxyMembershipID(const char *durableClientId = nullptr, const
@@ -70,9 +73,12 @@
   DSFid getDSFID() const override { return DSFid::InternalDistributedMember; }
   size_t objectSize() const override { return 0; }
 
-  void initObjectVars(const char* hostname, uint8_t* hostAddr,
-                      uint32_t hostAddrLen, bool hostAddrLocalMem,
-                      uint32_t hostPort, const char* durableClientId,
+  void initHostAddressVector(const ACE_INET_Addr& address);
+
+  void initHostAddressVector(const uint8_t* hostAddr, uint32_t hostAddrLen);
+
+  void initObjectVars(const char* hostname, uint32_t hostPort,
+                      const char* durableClientId,
                       const std::chrono::seconds durableClntTimeOut,
                       int32_t dcPort, int32_t vPID, int8_t vmkind,
                       int8_t splitBrainFlag, const char* dsname,
@@ -80,8 +86,10 @@
 
   std::string getDSName() const { return m_dsname; }
   std::string getUniqueTag() const { return m_uniqueTag; }
-  uint8_t* getHostAddr() const { return m_hostAddr; }
-  uint32_t getHostAddrLen() const { return m_hostAddrLen; }
+  const std::vector<uint8_t>& getHostAddr() const { return m_hostAddr; }
+  uint32_t getHostAddrLen() const {
+    return static_cast<uint32_t>(m_hostAddr.size());
+  }
   uint32_t getHostPort() const { return m_hostPort; }
   std::string getHashKey() override;
   int16_t compareTo(const DSMemberForVersionStamp&) const override;
@@ -113,12 +121,10 @@
 
   std::string m_dsname;
   uint32_t m_hostPort;
-  uint8_t* m_hostAddr;
-  uint32_t m_hostAddrLen;
-  uint32_t m_hostAddrAsUInt32;
+  std::vector<uint8_t> m_hostAddr;
+
   std::string m_uniqueTag;
   std::string m_hashKey;
-  bool m_hostAddrLocalMem;
   uint32_t m_vmViewId;
   static const uint8_t LONER_DM_TYPE = 13;
   static const int VERSION_MASK;
diff --git a/cppcache/src/ClientProxyMembershipIDFactory.cpp b/cppcache/src/ClientProxyMembershipIDFactory.cpp
index 62e6b6e..ceffcf9 100644
--- a/cppcache/src/ClientProxyMembershipIDFactory.cpp
+++ b/cppcache/src/ClientProxyMembershipIDFactory.cpp
@@ -53,11 +53,11 @@
 }
 
 std::unique_ptr<ClientProxyMembershipID> ClientProxyMembershipIDFactory::create(
-    const char* hostname, uint32_t hostAddr, uint32_t hostPort,
+    const char* hostname, const ACE_INET_Addr& address, uint32_t hostPort,
     const char* durableClientId,
     const std::chrono::seconds durableClntTimeOut) {
   return std::unique_ptr<ClientProxyMembershipID>(new ClientProxyMembershipID(
-      dsName, randString, hostname, hostAddr, hostPort, durableClientId,
+      dsName, randString, hostname, address, hostPort, durableClientId,
       durableClntTimeOut));
 }
 
diff --git a/cppcache/src/ClientProxyMembershipIDFactory.hpp b/cppcache/src/ClientProxyMembershipIDFactory.hpp
index 063938e..c969c37 100644
--- a/cppcache/src/ClientProxyMembershipIDFactory.hpp
+++ b/cppcache/src/ClientProxyMembershipIDFactory.hpp
@@ -22,6 +22,8 @@
 
 #include <string>
 
+#include <ace/INET_Addr.h>
+
 #include "ClientProxyMembershipID.hpp"
 
 namespace apache {
@@ -33,7 +35,7 @@
   explicit ClientProxyMembershipIDFactory(std::string dsName);
 
   std::unique_ptr<ClientProxyMembershipID> create(
-      const char* hostname, uint32_t hostAddr, uint32_t hostPort,
+      const char* hostname, const ACE_INET_Addr& address, uint32_t hostPort,
       const char* durableClientId = nullptr,
       const std::chrono::seconds durableClntTimeOut =
           std::chrono::seconds::zero());
diff --git a/cppcache/src/PoolFactory.cpp b/cppcache/src/PoolFactory.cpp
index 5b25227..1f42345 100644
--- a/cppcache/src/PoolFactory.cpp
+++ b/cppcache/src/PoolFactory.cpp
@@ -308,7 +308,17 @@
   }
 
   ACE_INET_Addr addr(port, host.c_str());
-  if (!(addr.get_ip_address())) {
+  // check unknown host
+  const int maxlength = 256;
+  const int maxhostlength = 256;
+  char char_array[maxlength];
+  char char_localhost[maxhostlength];
+
+  addr.get_host_name(char_array, maxlength);
+  gethostname(char_localhost, maxhostlength);  // get local hostname
+
+  if ((strcmp(char_localhost, host.c_str()) != 0) &&
+      (strcmp(char_localhost, char_array) == 0)) {
     throw IllegalArgumentException("Unknown host " + host);
   }
   return *this;
diff --git a/cppcache/src/ServerLocation.hpp b/cppcache/src/ServerLocation.hpp
index 1461203..a0ce231 100644
--- a/cppcache/src/ServerLocation.hpp
+++ b/cppcache/src/ServerLocation.hpp
@@ -56,7 +56,7 @@
     /*
     name = Utils::convertHostToCanonicalForm(name.c_str());
     */
-    auto position = name.find_first_of(":");
+    auto position = name.find_last_of(":");
     m_serverName = name.substr(0, position);
     m_port = std::stoi(name.substr(position + 1));
     makeEpString();
diff --git a/cppcache/src/TcpConn.cpp b/cppcache/src/TcpConn.cpp
index c8837c6..7cee9ab 100644
--- a/cppcache/src/TcpConn.cpp
+++ b/cppcache/src/TcpConn.cpp
@@ -94,7 +94,7 @@
 }
 
 void TcpConn::init() {
-  ACE_HANDLE sock = ACE_OS::socket(AF_INET, SOCK_STREAM, 0);
+  ACE_HANDLE sock = ACE_OS::socket(m_addr.get_type(), SOCK_STREAM, 0);
   if (sock == ACE_INVALID_HANDLE) {
     int32_t lastError = ACE_OS::last_error();
     LOGERROR("Failed to create socket. Errno: %d: %s", lastError,
diff --git a/cppcache/src/TcpSslConn.cpp b/cppcache/src/TcpSslConn.cpp
index b4b328e..22b59aa 100644
--- a/cppcache/src/TcpSslConn.cpp
+++ b/cppcache/src/TcpSslConn.cpp
@@ -57,7 +57,7 @@
   LOGDEBUG("Creating SSL socket stream");
   try {
     m_ssl = getSSLImpl(sock, m_pubkeyfile, m_privkeyfile);
-  } catch (std::exception e) {
+  } catch (std::exception& e) {
     throw SslException(e.what());
   }
 }
diff --git a/cppcache/src/TcrConnection.cpp b/cppcache/src/TcrConnection.cpp
index b2882f7..f847e91 100644
--- a/cppcache/src/TcrConnection.cpp
+++ b/cppcache/src/TcrConnection.cpp
@@ -173,7 +173,7 @@
     ACE_OS::hostname(hostName, sizeof(hostName) - 1);
 
     ACE_INET_Addr driver(hostName);
-    uint32_t hostAddr = driver.get_ip_address();
+
     uint16_t hostPort = 0;
 
     // Add 3 durable Subcription properties to ClientProxyMembershipID
@@ -184,7 +184,7 @@
     // Write ClientProxyMembershipID serialized object.
     uint32_t memIdBufferLength;
     auto memId = cacheImpl->getClientProxyMembershipIDFactory().create(
-        hostName, hostAddr, hostPort, durableId.c_str(), durableTimeOut);
+        hostName, driver, hostPort, durableId.c_str(), durableTimeOut);
     auto memIdBuffer = memId->getDSMemberId(memIdBufferLength);
     handShakeMsg.writeBytes(
         reinterpret_cast<int8_t*>(const_cast<char*>(memIdBuffer)),
diff --git a/cppcache/src/ThinClientPoolDM.cpp b/cppcache/src/ThinClientPoolDM.cpp
index 2d2fef9..abe59ce 100644
--- a/cppcache/src/ThinClientPoolDM.cpp
+++ b/cppcache/src/ThinClientPoolDM.cpp
@@ -178,7 +178,7 @@
   ACE_TCHAR hostName[256];
   ACE_OS::hostname(hostName, sizeof(hostName) - 1);
   ACE_INET_Addr driver(hostName);
-  uint32_t hostAddr = driver.get_ip_address();
+
   uint16_t hostPort = 0;
   auto&& durableId = sysProp.durableClientId();
 
@@ -189,7 +189,7 @@
 
   const auto durableTimeOut = sysProp.durableTimeout();
   m_memId = cacheImpl->getClientProxyMembershipIDFactory().create(
-      hostName, hostAddr, hostPort, clientDurableId.c_str(), durableTimeOut);
+      hostName, driver, hostPort, clientDurableId.c_str(), durableTimeOut);
 
   if (m_attrs->m_initLocList.size() == 0 &&
       m_attrs->m_initServList.size() == 0) {
diff --git a/cppcache/src/statistics/HostStatSampler.cpp b/cppcache/src/statistics/HostStatSampler.cpp
index 1fc5b8e..4b221d5 100644
--- a/cppcache/src/statistics/HostStatSampler.cpp
+++ b/cppcache/src/statistics/HostStatSampler.cpp
@@ -536,12 +536,12 @@
           ACE_TCHAR hostName[256];
           ACE_OS::hostname(hostName, sizeof(hostName) - 1);
           ACE_INET_Addr driver("", hostName, "tcp");
-          uint32_t hostAddr = driver.get_ip_address();
+
           uint16_t hostPort = 0;
 
           auto memId = conn_man->getCacheImpl()
                            ->getClientProxyMembershipIDFactory()
-                           .create(hostName, hostAddr, hostPort,
+                           .create(hostName, driver, hostPort,
                                    m_durableClientId, m_durableTimeout);
           clientId = memId->getDSMemberIdForThinClientUse();
         }
diff --git a/cppcache/test/ClientProxyMembershipIDFactoryTest.cpp b/cppcache/test/ClientProxyMembershipIDFactoryTest.cpp
deleted file mode 100644
index a1fc61f..0000000
--- a/cppcache/test/ClientProxyMembershipIDFactoryTest.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-#include <regex>
-
-#include <boost/endian/conversion.hpp>
-
-#include <gtest/gtest.h>
-
-#include "ClientProxyMembershipIDFactory.hpp"
-
-using apache::geode::client::ClientProxyMembershipIDFactory;
-
-TEST(ClientProxyMembershipIDFactoryTest, testCreate) {
-  ClientProxyMembershipIDFactory factory("myDs");
-
-  auto hostAddr = boost::endian::native_to_big(1);
-  auto id = factory.create("myHost", hostAddr, 2, "myClientID",
-                           std::chrono::seconds(3));
-  ASSERT_NE(nullptr, id);
-
-  EXPECT_EQ("myDs", id->getDSName());
-  EXPECT_EQ(hostAddr, *reinterpret_cast<uint32_t*>(id->getHostAddr()));
-  EXPECT_EQ(static_cast<uint32_t>(4), id->getHostAddrLen());
-  EXPECT_EQ(static_cast<uint32_t>(2), id->getHostPort());
-
-  auto uniqueTag = id->getUniqueTag();
-  ASSERT_NE("", uniqueTag);
-  EXPECT_EQ(std::string(":0:0:0:1:2:myDs:").append(uniqueTag),
-            id->getHashKey());
-  EXPECT_TRUE(std::regex_search(
-      id->getDSMemberIdForThinClientUse(),
-      std::regex(
-          std::string("myHost(.*):2:").append(uniqueTag).append(":myDs"))));
-}
diff --git a/cppcache/test/ClientProxyMembershipIDTest.cpp b/cppcache/test/ClientProxyMembershipIDTest.cpp
new file mode 100644
index 0000000..9af6e9f
--- /dev/null
+++ b/cppcache/test/ClientProxyMembershipIDTest.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#include <regex>
+#include <vector>
+
+#include <boost/endian/conversion.hpp>
+
+#include <gtest/gtest.h>
+
+#include "ClientProxyMembershipID.hpp"
+
+using apache::geode::client::ClientProxyMembershipID;
+
+TEST(ClientProxyMembershipIDTest, testCreate) {
+  uint32_t number = boost::endian::native_to_big(1);
+  const uint8_t* array = reinterpret_cast<uint8_t*>(&number);
+
+  ClientProxyMembershipID cpmID(array, 4, 2, "myDs", "uniqueTag", 0);
+
+  std::vector<uint8_t> vector;
+  vector.assign(array, array + 4);
+
+  EXPECT_EQ("myDs", cpmID.getDSName());
+  EXPECT_EQ(vector, cpmID.getHostAddr());
+  EXPECT_EQ(static_cast<uint32_t>(4), cpmID.getHostAddrLen());
+  EXPECT_EQ(static_cast<uint32_t>(2), cpmID.getHostPort());
+
+  auto uniqueTag = cpmID.getUniqueTag();
+  ASSERT_NE("", uniqueTag);
+  EXPECT_EQ(std::string(":0:0:0:1:2:myDs:").append(uniqueTag),
+            cpmID.getHashKey());
+  EXPECT_TRUE(std::regex_search(
+      cpmID.getDSMemberIdForThinClientUse(),
+      std::regex(
+          std::string("localhost(.*):2:").append(uniqueTag).append(":myDs"))));
+}
diff --git a/dependencies/ACE/config.h.in b/dependencies/ACE/config.h.in
index f820a30..46d56ae 100755
--- a/dependencies/ACE/config.h.in
+++ b/dependencies/ACE/config.h.in
@@ -27,5 +27,7 @@
 
 #endif // __cplusplus >= 201103L
 
+#define ACE_HAS_IPV6 1
+
 #include "ace/config-@ACE_CONFIG@.h"