[IOT-2054] Avoid calling CA API from the C++ layer
authorDan Mihai <Daniel.Mihai@microsoft.com>
Thu, 27 Apr 2017 03:07:54 +0000 (20:07 -0700)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Fri, 28 Apr 2017 21:34:43 +0000 (21:34 +0000)
Add OCGetIpv6AddrScope, a thin wrapper over CAGetIpv6AddrScope.

Change-Id: Idc573542c7a2b6103ff254399bd286515aa56d8e
Signed-off-by: Dan Mihai <Daniel.Mihai@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/19351
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/octbstack_product.def
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/stacktests.cpp
resource/src/OCResource.cpp

index e5012b9..33630c1 100644 (file)
@@ -875,7 +875,7 @@ OCPersistentStorage *OCGetPersistentStorageHandler();
 * @param[in] ifindex     interface index.
 * @param[out] zoneId     pointer of zoneId string, caller should free
 *                        zoneId using OICFree() when it returned CA_STATUS_OK.
-* @return Returns ::OC_STACK_OK if successful.
+* @return ::OC_STACK_OK if successful.
 */
 OCStackResult OCGetLinkLocalZoneId(uint32_t ifindex, char **zoneId);
 
@@ -895,10 +895,20 @@ OCStackResult OCGetLinkLocalZoneId(uint32_t ifindex, char **zoneId);
  *                          TLS_ECDH_anon_WITH_AES_128_CBC_SHA       0xC018
  * @param[in] adapterType transport adapter (TCP/IP/BLE)
  *
- * @return Returns ::OC_STACK_OK if successful.
+ * @return ::OC_STACK_OK if successful.
  */
 OCStackResult OCSelectCipherSuite(uint16_t cipher, OCTransportAdapter adapterType);
 
+/**
+ * Return the scope level of a given IP address.
+ *
+ * @param[in] addr          remote IP address.
+ * @param[out] scope        scope level of given IP address.
+ *
+ * @return ::OC_STACK_OK if successful.
+ */
+OCStackResult OCGetIpv6AddrScope(const char *addr, OCTransportFlags *scope);
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index e43ff97..528f08b 100644 (file)
@@ -50,6 +50,7 @@ OCGetDeviceId
 OCGetDeviceOwnedState
 OCGetDirectPairedDevices
 OCGetHeaderOption
+OCGetIpv6AddrScope
 OCGetNumberOfResources
 OCGetNumberOfResourceInterfaces
 OCGetNumberOfResourceTypes
index 0495a81..f019d7c 100644 (file)
@@ -6009,3 +6009,28 @@ OCStackResult OCSelectCipherSuite(uint16_t cipher, OCTransportAdapter adapterTyp
 
     return CAResultToOCResult(CASelectCipherSuite(cipher, (CATransportAdapter_t)adapterType));
 }
+
+OCStackResult OCGetIpv6AddrScope(const char *addr, OCTransportFlags *scope)
+{
+    // OCTransportFlags and CATransportFlags_t are using the same bits for each scope.
+    OC_STATIC_ASSERT(OC_SCOPE_INTERFACE     == CA_SCOPE_INTERFACE,  "OC/CA bit mismatch");
+    OC_STATIC_ASSERT(OC_SCOPE_LINK          == CA_SCOPE_LINK,       "OC/CA bit mismatch");
+    OC_STATIC_ASSERT(OC_SCOPE_REALM         == CA_SCOPE_REALM,      "OC/CA bit mismatch");
+    OC_STATIC_ASSERT(OC_SCOPE_ADMIN         == CA_SCOPE_ADMIN,      "OC/CA bit mismatch");
+    OC_STATIC_ASSERT(OC_SCOPE_SITE          == CA_SCOPE_SITE,       "OC/CA bit mismatch");
+    OC_STATIC_ASSERT(OC_SCOPE_ORG           == CA_SCOPE_ORG,        "OC/CA bit mismatch");
+    OC_STATIC_ASSERT(OC_SCOPE_GLOBAL        == CA_SCOPE_GLOBAL,     "OC/CA bit mismatch");
+
+    #define ALL_OC_SCOPES (OC_SCOPE_INTERFACE | OC_SCOPE_LINK | OC_SCOPE_REALM | OC_SCOPE_ADMIN |\
+                           OC_SCOPE_SITE | OC_SCOPE_ORG | OC_SCOPE_GLOBAL)
+
+    CAResult_t caResult = CAGetIpv6AddrScope(addr, (CATransportFlags_t *)scope);
+
+    if (CA_STATUS_OK == caResult)
+    {
+        assert(((*scope) & ~ALL_OC_SCOPES) == 0);
+        return OC_STACK_OK;
+    }
+
+    return CAResultToOCResult(caResult);
+}
index b5b53ee..435a1bb 100644 (file)
@@ -2878,3 +2878,197 @@ TEST(DiagnosticPayload, DISABLED_EndToEnd)
 
     OCStop();
 }
+
+// Mostly copy-paste from ca_api_unittest.cpp
+TEST(OCIpv6ScopeLevel, getMulticastScope)
+{
+    const char interfaceLocalStart[] = "ff01::";
+    const char linkLocalStart[]      = "ff02::";
+    const char realmLocalStart[]     = "ff03::";
+    const char adminLocalStart[]     = "ff04::";
+    const char siteLocalStart[]      = "ff05::";
+    const char orgLocalStart[]       = "ff08::";
+    const char globalStart[]         = "ff0e::";
+
+    const char interfaceLocalMid[] = "ff81:0000:0000:f000:0000:0000:0000:0000";
+    const char linkLocalMid[]      = "ff82:0000:0000:f000:0000:0000:0000:0000";
+    const char realmLocalMid[]     = "ff83:0000:0000:f000:0000:0000:0000:0000";
+    const char adminLocalMid[]     = "ff84:0000:0000:f000:0000:0000:0000:0000";
+    const char siteLocalMid[]      = "ff85:0000:0000:f000:0000:0000:0000:0000";
+    const char orgLocalMid[]       = "ff88:0000:0000:f000:0000:0000:0000:0000";
+    const char globalMid[]         = "ff8e:0000:0000:f000:0000:0000:0000:0000";
+
+    const char interfaceLocalEnd[] = "fff1:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char linkLocalEnd[]      = "fff2:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char realmLocalEnd[]     = "fff3:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char adminLocalEnd[]     = "fff4:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char siteLocalEnd[]      = "fff5:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char orgLocalEnd[]       = "fff8:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char globalEnd[]         = "fffe:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+    // range start
+    OCTransportFlags scopeLevel = OC_DEFAULT_FLAGS;
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(interfaceLocalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_INTERFACE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(linkLocalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_LINK, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(realmLocalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_REALM, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(adminLocalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_ADMIN, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(siteLocalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_SITE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(orgLocalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_ORG, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(globalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    // range mid
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(interfaceLocalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_INTERFACE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(linkLocalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_LINK, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(realmLocalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_REALM, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(adminLocalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_ADMIN, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(siteLocalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_SITE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(orgLocalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_ORG, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(globalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    // range end
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(interfaceLocalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_INTERFACE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(linkLocalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_LINK, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(realmLocalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_REALM, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(adminLocalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_ADMIN, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(siteLocalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_SITE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(orgLocalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_ORG, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(globalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+}
+
+// Mostly copy-paste from ca_api_unittest.cpp
+TEST(OCIpv6ScopeLevel, getUnicastScope)
+{
+    const char linkLocalLoopBack[]  = "::1";
+
+    const char linkLocalStart[]     = "fe80::";
+    const char linkLocalMid[]       = "fe80:0000:0000:0000:0f00:0000:0000:0000";
+    const char linkLocalEnd[]       = "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+    const char siteLocalStart[]     = "fec0::";
+    const char siteLocalMid[]       = "fec0:0000:0000:0000:0f00:0000:0000:0000";
+    const char siteLocalEnd[]       = "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+    const char globalStart[]   = "2000:0000:0000:0000:0000:0000:0000:0000";
+    const char globalMid[]     = "2000:0000:0000:0f00:0000:0000:0000:0000";
+    const char globalEnd[]     = "3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+    // loopback
+    OCTransportFlags scopeLevel = OC_DEFAULT_FLAGS;
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(linkLocalLoopBack, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_LINK, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    // linklocal
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(linkLocalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_LINK, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(linkLocalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_LINK, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(linkLocalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_LINK, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    // sitelocal
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(siteLocalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_SITE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(siteLocalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_SITE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(siteLocalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_SITE, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    // global
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(globalStart, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(globalMid, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+
+    EXPECT_EQ(OC_STACK_OK, OCGetIpv6AddrScope(globalEnd, &scopeLevel));
+    EXPECT_EQ(OC_SCOPE_GLOBAL, scopeLevel);
+    scopeLevel = OC_DEFAULT_FLAGS;
+}
+
+// Mostly copy-paste from ca_api_unittest.cpp
+TEST(OCIpv6ScopeLevel, invalidAddressTest)
+{
+    const char invalidAddr1[]    = "qqqq";
+    const char invalidAddr2[]    = "ffx7:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+    const char invalidAddr3[]    = "ffx7::::::::::dsds";
+    const char invalidAddr4[]    = "ffx7:ffff:ffff:ff@f:ffff:ffff:ffff:ffff";
+
+    OCTransportFlags scopeLevel = OC_DEFAULT_FLAGS;
+    EXPECT_EQ(OC_STACK_ERROR, OCGetIpv6AddrScope(invalidAddr1, &scopeLevel));
+    EXPECT_EQ(OC_STACK_ERROR, OCGetIpv6AddrScope(invalidAddr2, &scopeLevel));
+    EXPECT_EQ(OC_STACK_ERROR, OCGetIpv6AddrScope(invalidAddr3, &scopeLevel));
+    EXPECT_EQ(OC_STACK_ERROR, OCGetIpv6AddrScope(invalidAddr4, &scopeLevel));
+}
index f31c1e1..8fd1ed0 100644 (file)
@@ -339,17 +339,17 @@ std::string OCResource::setHost(const std::string& host)
         else
         {
             // It means zone-id is missing, check ipv6Addr is link local
-            CATransportFlags_t scopeLevel;
-            CAResult_t caResult = CAGetIpv6AddrScope(ip6Addr.c_str(), &scopeLevel);
+            OCTransportFlags scopeLevel;
+            OCStackResult ocResult = OCGetIpv6AddrScope(ip6Addr.c_str(), &scopeLevel);
 
-            if (CA_STATUS_OK != caResult)
+            if (OC_STACK_OK != ocResult)
             {
                 throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
                     m_interfaces.empty(), m_clientWrapper.expired(), false, false);
             }
             else
             {
-                if (CA_SCOPE_LINK == scopeLevel)
+                if (OC_SCOPE_LINK == scopeLevel)
                 {
                     {
                         // Given ip address is link-local scope without zone-id.