Additional functionality for MOT and pin handling.
authorAlex Kelley <alexke@microsoft.com>
Tue, 6 Dec 2016 01:11:55 +0000 (17:11 -0800)
committerKevin Kane <kkane@microsoft.com>
Thu, 19 Jan 2017 17:59:38 +0000 (17:59 +0000)
 - Add APIs to do MOT discovery of a specific device.
 - Add APIs to check to see if the caller is a subowner.
 - Add context to display and input pin callbacks.
 - Add device information to input pin callback.
 - Enable C++ security APIs to be built for Windows.
 - Update ProvisioningClient and Sampleserver_RandomPin
   to  use the new APIs.
 - Enable MOT to always build on Windows.

Change-Id: I27af9d3c2c7065b8643f77be3ac4c9b2dc5ffe80
Signed-off-by: Alex Kelley <alexke@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/16403
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Mike Fenelon <mike.fenelon@microsoft.com>
Reviewed-by: Kevin Kane <kkane@microsoft.com>
19 files changed:
resource/csdk/connectivity/test/ssladapter_test.cpp
resource/csdk/octbstack_product_secured.def
resource/csdk/octbstack_product_secured_mot.def
resource/csdk/security/include/pinoxmcommon.h
resource/csdk/security/provisioning/include/ocprovisioningmanager.h
resource/csdk/security/provisioning/include/pmutility.h
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/sample/sampleserver_randompin.cpp
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/oxmrandompin.c
resource/csdk/security/provisioning/src/pmutility.c
resource/csdk/security/src/oxmpincommon.c
resource/include/OCProvisioningManager.hpp
resource/provisioning/SConscript
resource/provisioning/examples/provisioningclient.cpp
resource/provisioning/examples/subownerclient.cpp
resource/provisioning/src/OCProvisioningManager.cpp
resource/src/SConscript
run.bat

index 9ebdcf4..e4e5cfe 100644 (file)
@@ -21,6 +21,7 @@
 #include "gtest/gtest.h"
 #include "time.h"
 
+// Test function hooks
 #define CAcloseSslConnection CAcloseSslConnectionTest
 #define CAdecryptSsl CAdecryptSslTest
 #define CAdeinitSslAdapter CAdeinitSslAdapterTest
@@ -33,6 +34,9 @@
 #define CAsetTlsCipherSuite CAsetTlsCipherSuiteTest
 #define CAsslGenerateOwnerPsk CAsslGenerateOwnerPskTest
 #define CAcloseSslConnectionAll CAcloseSslConnectionAllTest
+#ifdef MULTIPLE_OWNER
+#define GetCASecureEndpointData GetCASecureEndpointDataTest
+#endif
 
 #include "../src/adapter_util/ca_adapter_net_ssl.c"
 
index b047ec4..f524b63 100644 (file)
@@ -1,6 +1,8 @@
 ; Windows octbstack.dll exports that are required for both products and tests,
 ; but only when building with SECURED=1.
 
+ConvertUuidToStr
+
 CreateJustWorksOwnerTransferPayload
 CreateJustWorksSelectOxmPayload
 CreateMVJustWorksSelectOxmPayload
@@ -18,6 +20,7 @@ OCDeleteDiscoveredDevices
 OCDeletePdAclList
 OCDeleteUuidList
 OCDiscoverOwnedDevices
+OCDiscoverSingleDevice
 OCDiscoverUnownedDevices
 OCDoOwnershipTransfer
 OCGetACLResource
@@ -30,16 +33,27 @@ OCSaveACL
 OCProvisionCredentials
 OCProvisionDirectPairing
 OCProvisionPairwiseDevices
+OCProvisionTrustCertChain
+OCReadTrustCertChain
+OCRegisterTrustCertChainNotifier
 OCRemoveDevice
 OCRemoveDeviceWithUuid
+OCRemoveTrustCertChainNotifier
 OCResetDevice
 OCResetSVRDB
+OCSaveTrustCertChain
 OCSetOwnerTransferCallbackData
 OCUnlinkDevices
 OCSetOxmAllowStatus
 
+SetDisplayPinWithContextCB
+UnsetDisplayPinWithContextCB
 SetGeneratePinCB
+UnsetGeneratePinCB
 SetInputPinCB
+SetInputPinWithContextCB
+UnsetInputPinCB
+UnsetInputPinWithContextCB
 SetRandomPinPolicy
 SetDisplayNumCB
 UnsetDisplayNumCB
index 0fc058c..1479bd0 100644 (file)
@@ -11,7 +11,9 @@ OCAddPreconfigPin
 OCChangeMOTMode
 OCDiscoverMultipleOwnedDevices
 OCDiscoverMultipleOwnerEnabledDevices
+OCDiscoverMultipleOwnerEnabledSingleDevice
 OCDoMultipleOwnershipTransfer
+OCIsSubownerOfDevice
 OCProvisionPreconfigPin
 OCSelectMOTMethod
 
index c624117..a688176 100644 (file)
@@ -49,44 +49,101 @@ typedef enum OicSecPinType{
 }OicSecPinType_t;
 
 /**
- * Function pointer to print pin code.
+ * Function pointer to display pin code.
  */
 typedef void (*GeneratePinCallback)(char* pinData, size_t pinSize);
 
 /**
+ * Function pointer to display pin code, with context.
+ */
+typedef void(*DisplayPinCallbackWithContext)(char* pinData, size_t pinSize, void* context);
+
+/**
  * Function pointer to input pin code.
  */
 typedef void (*InputPinCallback)(char* pinBuf, size_t bufSize);
 
 /**
- * Function to setting generate PIN callback from user.
+ * Function pointer to input pin code, with context and device information.
+ */
+typedef void(*InputPinCallbackWithContext)(OicUuid_t deviceId, char* pinBuffer, size_t pinBufferSize, void* context);
+
+/**
+ * Function to set the display PIN callback from the user.
+ *
+ * @deprecated Use SetDisplayPinWithContextCB instead.
  *
  * @param pinCB implementation of generate PIN callback.
  */
 void SetGeneratePinCB(GeneratePinCallback pinCB);
 
 /**
- * Function to setting input PIN callback from user.
+ * Function to set the display PIN callback from the user with context.
+ *
+ * @param displayPinCB  implementation of display PIN callback.
+ * @param context       context to return in the callback.
+ *
+ * @return OC_STACK_OK in case of success or other value in case of error.
+ *         OC_STACK_INVALID_PARAM if pinCB is invalid.
+ *         OC_STACK_DUPLICATE_REQUEST if a display pin callback has already been set.
+ */
+OCStackResult SetDisplayPinWithContextCB(DisplayPinCallbackWithContext displayPinCB, void* context);
+
+/**
+ * Function to set the input PIN callback from the user.
+ *
+ * @deprecated Use SetInputPinWithContextCB instead.
  *
  * @param pinCB implementation of input PIN callback.
  */
 void SetInputPinCB(InputPinCallback pinCB);
 
 /**
+ * Function to set the input PIN callback from the user with context.
+ *
+ * @param inputPinCB  implementation of input PIN callback.
+ * @param context     context to return in the callback.
+ *
+ * @return OC_STACK_OK in case of success or other value in case of error.
+ *         OC_STACK_INVALID_PARAM if pinCB is invalid. 
+ *         OC_STACK_DUPLICATE_REQUEST if an input pin callback has already been set.
+ */
+OCStackResult SetInputPinWithContextCB(InputPinCallbackWithContext inputPinCB, void* context);
+
+/**
  * Function to unset the input PIN callback.
- * NOTE : Do not call this function while PIN based ownership transfer.
+ * NOTE : Do not call this function while PIN based ownership transfer is in progress.
+ *
+ * @deprecated Use UnsetInputPinWithContextCB instead.
+ *
  */
 void UnsetInputPinCB();
 
 /**
+ * Function to unset the input PIN callback.
+ * NOTE : Do not call this function while PIN based ownership transfer is in progress.
+ */
+void UnsetInputPinWithContextCB();
+
+/**
  * Function to unset the PIN generation callback.
- * NOTE : Do not call this function while PIN based ownership transfer.
+ * NOTE : Do not call this function while PIN based ownership transfer is in progress.
+ *
+ * @deprecated Use UnsetDisplayPinWithContextCB instead.
+ *
  */
 void UnsetGeneratePinCB();
 
 /**
- * Function to generate random PIN.
- * This function will send generated PIN to user via callback.
+ * Function to unset the PIN display callback.
+ * NOTE : Do not call this function while PIN based ownership transfer is in progress.
+ */
+void UnsetDisplayPinWithContextCB();
+
+/**
+ * Function to generate a random PIN.
+ * This function will send a generated PIN to the user via the callback that was set in
+ * SetGeneratePinCB or SetGeneratePinWithContextCB.
  *
  * @param pinBuffer is the reference to the buffer to store the generated PIN data.
  * @param bufferSize is the size of buffer.
@@ -96,14 +153,17 @@ void UnsetGeneratePinCB();
 OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize);
 
 /**
- * Function to input PIN callback via input callback.
+ * Function to get a pin for a device.
+ * This function will acquire a pin from the user via the callback that was set in 
+ * SetInputPinCB or SetInputPinWithContextCB. 
  *
+ * @param[in] deviceId is the device that is requesting a pin
  * @param[in,out] pinBuffer is the reference to the buffer to store the inputed PIN data.
  * @param[in] bufferSize is the size of buffer.
  *
  * @return ::OC_STACK_OK in case of success or other value in ccase of error.
  */
-OCStackResult InputPin(char* pinBuffer, size_t bufferSize);
+OCStackResult InputPin(OicUuid_t deviceId, char* pinBuffer, size_t bufferSize);
 
 #ifdef MULTIPLE_OWNER
 /**
@@ -118,7 +178,7 @@ OCStackResult SetPreconfigPin(const char *pinBuffer, size_t pinLength);
 #endif
 
 /**
- * Function to setting the policy for random PIN generation
+ * Function to set the policy for random PIN generation
  *
  * @param[in] pinSize Byte length of random PIN
  * @param[in] pinType Type of random PIN (ref OicSecPinType)
index da4c0f2..b205467 100644 (file)
@@ -56,23 +56,23 @@ OCStackResult OCInitPM(const char* dbPath);
  */\r
 OCStackResult OCDiscoverSingleDevice(unsigned short timeout, const OicUuid_t* deviceID,\r
                              OCProvisionDev_t **ppFoundDevice);\r
-
-/**
- * The function is responsible for discovery of owned/unowned device is specified endpoint/MAC
- * address.
- * It will return the found device even though timeout is not exceeded.
- *
- * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
- *                    server before returning the device.
- * @param[in] deviceID         deviceID of target device.
- * @param[in] hostAddress       MAC address of target device.
- * @param[in] connType       ConnectivityType for discovery.
- * @param[out] ppFoundDevice     OCProvisionDev_t of found device.
- * @return OTM_SUCCESS in case of success and other value otherwise.
- */
-OCStackResult OCDiscoverSingleDeviceInUnicast(unsigned short timeout, const OicUuid_t* deviceID,
-                             const char* hostAddress, OCConnectivityType connType,
-                             OCProvisionDev_t **ppFoundDevice);
+\r
+/**\r
+ * The function is responsible for discovery of owned/unowned device is specified endpoint/MAC\r
+ * address.\r
+ * It will return the found device even though timeout is not exceeded.\r
+ *\r
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
+ *                    server before returning the device.\r
+ * @param[in] deviceID         deviceID of target device.\r
+ * @param[in] hostAddress       MAC address of target device.\r
+ * @param[in] connType       ConnectivityType for discovery.\r
+ * @param[out] ppFoundDevice     OCProvisionDev_t of found device.\r
+ * @return OTM_SUCCESS in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDiscoverSingleDeviceInUnicast(unsigned short timeout, const OicUuid_t* deviceID,\r
+                             const char* hostAddress, OCConnectivityType connType,\r
+                             OCProvisionDev_t **ppFoundDevice);\r
 \r
 /**\r
  * The function is responsible for discovery of device is current subnet. It will list\r
@@ -144,6 +144,22 @@ OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **
 \r
 #ifdef MULTIPLE_OWNER\r
 /**\r
+ * The function is responsible for the discovery of an MOT-enabled device with the specified deviceID.\r
+ * The function will return when security information for device with deviceID has been obtained or the \r
+ * timeout has been exceeded.\r
+ *\r
+ * @param[in]  timeoutSeconds  Maximum time, in seconds, this function will listen for responses from \r
+ *                             servers before returning.\r
+ * @param[in]  deviceID        deviceID of target device.\r
+ * @param[out] ppFoundDevice   OCProvisionDev_t of discovered device. Caller should use\r
+ *                             OCDeleteDiscoveredDevices to delete the device.\r
+ * @return OC_STACK_OK in case of success and other values otherwise.\r
+ */\r
+OCStackResult OCDiscoverMultipleOwnerEnabledSingleDevice(unsigned short timeoutSeconds,\r
+                                                         const OicUuid_t *deviceID, \r
+                                                         OCProvisionDev_t **ppFoundDevice);\r
+\r
+/**\r
  * The function is responsible for discovery of MOT enabled device is current subnet.\r
  *\r
  * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
@@ -162,6 +178,15 @@ OCStackResult OCDiscoverMultipleOwnerEnabledDevices(unsigned short timeout, OCPr
  * @return OC_STACK_OK in case of success and other value otherwise.\r
  */\r
 OCStackResult OCDiscoverMultipleOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList);\r
+\r
+/**\r
+ * The function is responsible for determining if the caller is a subowner of the specified device.\r
+ *\r
+ * @param[in]  device      MOT enabled device that contains a list of subowners.\r
+ * @param[out] isSubowner  Bool indicating whether the caller is a subowner of device.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCIsSubownerOfDevice(OCProvisionDev_t *device, bool *isSubowner);\r
 #endif //MULTIPLE_OWNER\r
 \r
 /**\r
index f192d8c..640175c 100644 (file)
@@ -86,6 +86,24 @@ OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisi
 
 #ifdef MULTIPLE_OWNER
 /**
+ * The function is responsible for the discovery of an MOT-enabled device with the specified deviceID.
+ * The function will return when security information for device with deviceID has been obtained or the
+ * timeout has been exceeded.
+ *
+ * @param[in]  timeoutSeconds  Maximum time, in seconds, this function will listen for responses from 
+ *                             servers before returning.
+ * @param[in]  deviceID        deviceID of target device.
+ * @param[out] ppFoundDevice   OCProvisionDev_t of found device. Caller should use PMDeleteDeviceList 
+ *                             to delete the device.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ *         OC_STACK_INVALID_PARAM when deviceID is NULL or ppFoundDevice is not initailized.
+ */
+OCStackResult PMMultipleOwnerSingleDeviceDiscovery(unsigned short timeoutSeconds,
+                                                   const OicUuid_t *deviceID,
+                                                   OCProvisionDev_t **ppFoundDevice);
+
+/**
  * Discover multiple OTM enabled devices in the same IP subnet.
  *
  * @param[in] waittime      Timeout in seconds.
@@ -95,6 +113,16 @@ OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisi
  * @return OC_STACK_OK on success otherwise error.
  */
 OCStackResult PMMultipleOwnerDeviceDiscovery(unsigned short waittime, bool isMultipleOwned, OCProvisionDev_t **ppDevicesList);
+
+/**
+ * The function is responsible for determining if the caller is a subowner of the specified device.
+ *
+ * @param[in]  device      MOT enabled device that contains a list of subowners
+ * @param[out] isSubowner  Bool indicating whether the caller is a subowner of device
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PMIsSubownerOfDevice(OCProvisionDev_t *device, bool *isSubowner);
 #endif //MULTIPLE_OWNER
 
 /**
index 8000849..b84ae26 100644 (file)
@@ -50,6 +50,7 @@ extern "C"
 #define _12_DISCOV_OWN_DEVS_        12
 #ifdef MULTIPLE_OWNER
 #define _13_MOT_DISCOV_DEV_         13
+#define _14_MOT_DISCOV_SINGLE_DEV_  14
 #endif //MULTIPLE_OWNER
 #define _20_REGIST_DEVS_            20
 #define _30_PROVIS_PAIR_DEVS_       30
@@ -281,7 +282,7 @@ static void updateDoxmForMOTCB(void* ctx, int nOfRes, OCProvisionResult_t* arr,
 }
 #endif //MULTIPLE_OWNER
 
-static void inputPinCB(char* pin, size_t len)
+static void inputPinCB(OicUuid_t deviceId, char *pin, size_t len, void *context)
 {
     if(!pin || OXM_RANDOM_PIN_MIN_SIZE > len)
     {
@@ -342,7 +343,7 @@ static int initProvisionClient(void)
         return -1;
     }
 
-    SetInputPinCB(inputPinCB);
+    SetInputPinWithContextCB(inputPinCB, NULL);
 
     return 0;
 }
@@ -361,7 +362,7 @@ static int discoverAllDevices(void)
         g_unown_list = NULL;
     }
 
-    // call |OCGetDevInfoFromNetwork| API actually
+    // call |OCGetDevInfoFromNetwork| API
     printf("   Discovering All Un/Owned Devices on Network..\n");
     if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
     {
@@ -391,7 +392,7 @@ static int discoverUnownedDevices(void)
         g_unown_list = NULL;
     }
 
-    // call |OCDiscoverUnownedDevices| API actually
+    // call |OCDiscoverUnownedDevices| API
     printf("   Discovering Only Unowned Devices on Network..\n");
     if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
     {
@@ -417,7 +418,7 @@ static int discoverOwnedDevices(void)
         g_own_list = NULL;
     }
 
-    // call |OCDiscoverOwnedDevices| API actually
+    // call |OCDiscoverOwnedDevices| API
     printf("   Discovering Only Owned Devices on Network..\n");
     if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
     {
@@ -444,7 +445,7 @@ static int discoverMOTEnabledDevices(void)
         g_mot_enable_list = NULL;
     }
 
-    // call |OCDiscoverOwnedDevices| API actually
+    // call |OCDiscoverOwnedDevices| API
     printf("   Discovering Multiple Ownership Transfer Enabled Devices on Network..\n");
     if(OC_STACK_OK != OCDiscoverMultipleOwnerEnabledDevices(DISCOVERY_TIMEOUT, &g_mot_enable_list))
     {
@@ -458,6 +459,50 @@ static int discoverMOTEnabledDevices(void)
 
     return 0;
 }
+
+static int discoverSingleMOTEnabledDevice(void)
+{
+    OicUuid_t uuid = { .id = { 0 } };
+    char strUuid[64] = { 0 };
+
+    // Delete owned device list before updating it
+    if (g_mot_enable_list)
+    {
+        OCDeleteDiscoveredDevices(g_mot_enable_list);
+        g_mot_enable_list = NULL;
+    }
+
+    // Get the device id
+    printf("   Specify the Multiple Ownership Transfer enabled device to discover on the network\n");
+    printf("   > Input the UUID : ");
+    for (int ret = 0; 1 != ret; )
+    {
+        ret = scanf("%64s", strUuid);
+        for (; 0x20 <= getchar(); );  // for removing overflow garbages
+                                      // '0x20<=code' is character region
+    }
+
+    OCStackResult rst = ConvertStrToUuid(strUuid, &uuid);
+    if (OC_STACK_OK != rst)
+    {
+        OIC_LOG_V(ERROR, TAG, "ConvertStrToUuid API error: %d", rst);
+        return -1;
+    }
+
+    // Call |OCDiscoverMultipleOwnerEnabledSingleDevice| API
+    printf("   Discovering the Multiple Ownership Transfer enabled device on the network..\n");
+    if (OC_STACK_OK != OCDiscoverMultipleOwnerEnabledSingleDevice(DISCOVERY_TIMEOUT, &uuid, &g_mot_enable_list))
+    {
+        OIC_LOG(ERROR, TAG, "OCDiscoverMultipleOwnerEnabledSingleDevice API error");
+        return -1;
+    }
+
+    // Display the discovered owned list
+    printf("   > Discovered Multiple Ownership Transfer Enabled Device\n");
+    g_mot_enable_cnt = printDevList(g_mot_enable_list);
+
+    return 0;
+}
 #endif //MULTIPLE_OWNER
 
 static int registerDevices(void)
@@ -470,7 +515,7 @@ static int registerDevices(void)
         return 0;  // normal case
     }
 
-    // call |OCDoOwnershipTransfer| API actually
+    // call |OCDoOwnershipTransfer| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -524,7 +569,7 @@ static int provisionPairwise(void)
         }
     }
 
-    // call |OCProvisionPairwiseDevices| API actually
+    // call |OCProvisionPairwiseDevices| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -611,7 +656,7 @@ static int provisionCred(void)
     }
 
 
-    // call |OCProvisionCredentials| API actually
+    // call |OCProvisionCredentials| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -677,7 +722,7 @@ static int provisionAcl(void)
         goto PVACL_ERROR;
     }
 
-    // call |OCProvisionACL| API actually
+    // call |OCProvisionACL| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -775,7 +820,7 @@ static int provisionDirectPairing(void)
         goto PVDP_ERROR;
     }
 
-    // call |OCProvisionDirectPairing| API actually
+    // call |OCProvisionDirectPairing| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -837,7 +882,7 @@ static int checkLinkedStatus(void)
         printf("     Entered Wrong Number. Please Enter Again\n");
     }
 
-    // call |OCGetLinkedStatus| API actually
+    // call |OCGetLinkedStatus| API
     printf("   Checking Selected Link Status on PRVN DB..\n");
     OCUuidList_t* dvid_lst = NULL;
     size_t dvid_cnt = 0;
@@ -932,7 +977,7 @@ static int saveAcl(void)
         goto SVACL_ERROR;
     }
 
-    // call |OCSaveACL| API actually
+    // call |OCSaveACL| API
     rst = OCSaveACL(acl);
     if(OC_STACK_OK != rst)
     {
@@ -979,7 +1024,7 @@ static int getCred(void)
         printf("     Entered Wrong Number. Please Enter Again\n");
     }
 
-    // call |getDevInst| API actually
+    // call |getDevInst| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -1038,7 +1083,7 @@ static int getAcl(void)
         printf("     Entered Wrong Number. Please Enter Again\n");
     }
 
-    // call |getDevInst| API actually
+    // call |getDevInst| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -1088,7 +1133,7 @@ static int unlinkPairwise(void)
         return -1;
     }
 
-    // call |OCUnlinkDevices| API actually
+    // call |OCUnlinkDevices| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -1144,7 +1189,7 @@ static int removeDevice(void)
         printf("     Entered Wrong Number. Please Enter Again\n");
     }
 
-    // call |OCRemoveDevice| API actually
+    // call |OCRemoveDevice| API
     // calling this API with callback actually acts like blocking
     // for error checking, the return value saved and printed
     g_doneCB = false;
@@ -2104,7 +2149,8 @@ static void printMenu(void)
     printf("** 11. Discover Only Unowned Devices on Network\n");
 #ifdef MULTIPLE_OWNER
     printf("** 12. Discover Only Owned Devices on Network\n");
-    printf("** 13. Discover Multiple Ownership Transfer Enabled Devices on Network\n\n");
+    printf("** 13. Discover Multiple Ownership Transfer Enabled Devices on Network\n");
+    printf("** 14. Discover Specific Multiple Ownership Transfer Enabled Device on Network\n\n");
 #else
     printf("** 12. Discover Only Owned Devices on Network\n\n");
 #endif //MULTIPLE_OWNER
@@ -2240,6 +2286,12 @@ int main()
                 OIC_LOG(ERROR, TAG, "_13_MOT_DISCOV_DEV_: error");
             }
             break;
+        case _14_MOT_DISCOV_SINGLE_DEV_:
+            if (discoverSingleMOTEnabledDevice())
+            {
+                OIC_LOG(ERROR, TAG, "_14_MOT_DISCOV_SINGLE_DEV_: error");
+            }
+            break;
 #endif //MULTIPLE_OWNER
         case _20_REGIST_DEVS_:
             if(registerDevices())
index a7caaa2..c52456e 100644 (file)
@@ -447,7 +447,7 @@ FILE* server_fopen(const char *path, const char *mode)
     return fopen(CRED_FILE, mode);
 }
 
-void GeneratePinCB(char* pin, size_t pinSize)
+void DisplayPinCB(char *pin, size_t pinSize, void *context)
 {
     if(NULL == pin || pinSize <= 0)
     {
@@ -475,10 +475,10 @@ int main()
     }
 
    /**
-     * If server supported random pin based ownership transfer,
-     * callback of print PIN should be registered before runing server.
+     * If the server supports random pin based ownership transfer, the callback
+     * to display a PIN should be registered before running the server.
      */
-    SetGeneratePinCB(GeneratePinCB);
+    SetDisplayPinWithContextCB(DisplayPinCB, NULL);
 
     /**
      * Random PIN generation policy can be changed through SetRandomPinPolicy() API.
index 913e4c5..fd5d4a3 100644 (file)
@@ -170,6 +170,30 @@ OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **
 
 #ifdef MULTIPLE_OWNER
 /**
+ * The function is responsible for the discovery of an MOT-enabled device with the specified deviceID.
+ * The function will return when security information for device with deviceID has been obtained or the
+ * timeout has been exceeded.
+ *
+ * @param[in]  timeoutSeconds  Maximum time, in seconds, this function will listen for responses from 
+ *                             servers before returning.
+ * @param[in]  deviceID        deviceID of target device.
+ * @param[out] ppFoundDevice   OCProvisionDev_t of discovered device. Caller should use
+ *                             OCDeleteDiscoveredDevices to delete the device.
+ * @return OC_STACK_OK in case of success and other values otherwise.
+ */
+OCStackResult OCDiscoverMultipleOwnerEnabledSingleDevice(unsigned short timeoutSeconds,
+                                                         const OicUuid_t* deviceID, 
+                                                         OCProvisionDev_t **ppFoundDevice)
+{
+    if ((NULL == ppFoundDevice) || (NULL != *ppFoundDevice) || (0 == timeoutSeconds) || (NULL == deviceID))
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    return PMMultipleOwnerSingleDeviceDiscovery(timeoutSeconds, deviceID, ppFoundDevice);
+}
+
+/**
  * The function is responsible for discovery of MOT enabled device is current subnet.
  *
  * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
@@ -211,7 +235,6 @@ OCStackResult OCDiscoverMultipleOwnedDevices(unsigned short timeout, OCProvision
  * @param[in] targetDeviceInfo Selected target device.
  * @param[in] preconfigPin Preconfig PIN which is used while multiple owner authentication
  * @param[in] preconfigPinLen Byte length of preconfigPin
- *
  * @return OC_STACK_OK in case of success and other value otherwise.
  */
 OCStackResult OCAddPreconfigPin(const OCProvisionDev_t *targetDeviceInfo,
@@ -237,6 +260,22 @@ OCStackResult OCDoMultipleOwnershipTransfer(void* ctx,
     return MOTDoOwnershipTransfer(ctx, targetDevices, resultCallback);
 }
 
+/**
+ * The function is responsible for determining if the caller is a subowner of the specified device.
+ *
+ * @param[in]  device      MOT enabled device that contains a list of subowners
+ * @param[out] isSubowner  Bool indicating whether the caller is a subowner of device
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCIsSubownerOfDevice(OCProvisionDev_t *device, bool *isSubowner)
+{
+    if ((NULL == device) || (NULL == isSubowner))
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    return PMIsSubownerOfDevice(device, isSubowner);
+}
 #endif //MULTIPLE_OWNER
 
 /**
index 1df8940..24c2248 100644 (file)
@@ -80,7 +80,7 @@ OCStackResult InputPinCodeCallback(OTMContext_t *otmCtx)
 
     uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
 
-    OCStackResult res = InputPin((char*)pinData, sizeof(pinData));
+    OCStackResult res = InputPin(otmCtx->selectedDeviceInfo->doxm->deviceID, (char*)pinData, sizeof(pinData));
     if (OC_STACK_OK != res)
     {
         OIC_LOG(ERROR, TAG, "Failed to input PIN");
index 1d266c6..e310ba1 100644 (file)
@@ -48,6 +48,8 @@
 
 #include "srmutility.h"
 
+static const uint64_t USECS_PER_MSEC = 1000;
+
 #define TAG ("OIC_PM_UTILITY")
 
 typedef struct _DiscoveryInfo{
@@ -1163,7 +1165,8 @@ static OCStackApplicationResult MOTDeviceDiscoveryHandler(void *ctx, OCDoHandle
                 // Get my device ID from doxm resource
                 OicUuid_t myId;
                 memset(&myId, 0, sizeof(myId));
-                OCStackResult res = GetDoxmDevOwnerId(&myId);
+
+                res = GetDoxmDeviceID(&myId);
                 if(OC_STACK_OK != res)
                 {
                     OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
@@ -1171,16 +1174,18 @@ static OCStackApplicationResult MOTDeviceDiscoveryHandler(void *ctx, OCDoHandle
                     return OC_STACK_KEEP_TRANSACTION;
                 }
 
-                res = GetDoxmDeviceID(&myId);
-                if(OC_STACK_OK != res)
+                //if targetId and discovered deviceID are different, discard it
+                if ((pDInfo->isSingleDiscovery) &&
+                    (0 != memcmp(&ptrDoxm->deviceID.id, &pDInfo->targetId->id, sizeof(pDInfo->targetId->id))))
                 {
-                    OIC_LOG(ERROR, TAG, "Error while getting my UUID.");
+                    OIC_LOG(DEBUG, TAG, "Discovered device is not target device");
                     DeleteDoxmBinData(ptrDoxm);
                     return OC_STACK_KEEP_TRANSACTION;
                 }
+
                 //if this is owned discovery and this is PT's reply, discard it
-                if((pDInfo->isOwnedDiscovery) &&
-                        (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id))) )
+                if (((pDInfo->isSingleDiscovery) || (pDInfo->isOwnedDiscovery)) &&
+                    (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id))))
                 {
                     OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
                     DeleteDoxmBinData(ptrDoxm);
@@ -1268,6 +1273,101 @@ static OCStackApplicationResult MOTDeviceDiscoveryHandler(void *ctx, OCDoHandle
     return  OC_STACK_DELETE_TRANSACTION;
 }
 
+/**
+ * The function is responsible for the discovery of an MOT-enabled device with the specified deviceID.
+ * The function will return when security information for device with deviceID has been obtained or the
+ * timeout has been exceeded.
+ *
+ * @param[in]  timeoutSeconds  Maximum time, in seconds, this function will listen for responses from
+ *                             servers before returning.
+ * @param[in]  deviceID        deviceID of target device.
+ * @param[out] ppFoundDevice   OCProvisionDev_t of found device. Caller should use PMDeleteDeviceList 
+ *                             to delete the device.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ *         OC_STACK_INVALID_PARAM when deviceID is NULL or ppFoundDevice is not initailized.
+ */
+OCStackResult PMMultipleOwnerSingleDeviceDiscovery(unsigned short timeoutSeconds,
+                                                   const OicUuid_t* deviceID,
+                                                   OCProvisionDev_t **ppFoundDevice)
+{
+    OIC_LOG(DEBUG, TAG, "IN PMMultipleOwnerSingleDeviceDiscovery");
+
+    if ((NULL == ppFoundDevice) || (NULL == deviceID))
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    DiscoveryInfo discoveryInfo;
+    discoveryInfo.ppDevicesList = ppFoundDevice;
+    discoveryInfo.pCandidateList = NULL;
+    discoveryInfo.isOwnedDiscovery = false;
+    discoveryInfo.isSingleDiscovery = true;
+    discoveryInfo.isFound = false;
+    discoveryInfo.targetId = deviceID;
+
+    OCCallbackData cbData;
+    cbData.cb = &MOTDeviceDiscoveryHandler;
+    cbData.context = (void *)&discoveryInfo;
+    cbData.cd = NULL;
+
+    OCStackResult res = OC_STACK_ERROR;
+    const char query[] = "/oic/sec/doxm?mom!=0&owned=TRUE";
+
+    OCDoHandle handle = NULL;
+    res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0, CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
+    if (res != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+        return res;
+    }
+
+    //Waiting for each response.
+    uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
+    while ((OC_STACK_OK == res) && !discoveryInfo.isFound)
+    {
+        uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
+        if (currTime >= startTime)
+        {
+            long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
+            if (elapsed > timeoutSeconds)
+            {
+                break;
+            }
+
+            // Sleep for 100 ms to free up the CPU
+            usleep(100 * USECS_PER_MSEC);
+
+            res = OCProcess();
+        }
+        else
+        {
+            // System time has changed so we cannot reliably continue processing.
+            // Function returns with no device discovered.
+            break;
+        }
+    }
+
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "Failed while waiting for a secure discovery response.");
+        OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+        if (OC_STACK_OK != resCancel)
+        {
+            OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+        }
+        return res;
+    }
+
+    res = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to remove the registered callback");
+        return res;
+    }
+    OIC_LOG(DEBUG, TAG, "OUT PMMultipleOwnerSingleDeviceDiscovery");
+    return res;
+}
 
 /**
  * Discover multiple OTM enabled devices in the same IP subnet.
@@ -1345,6 +1445,46 @@ OCStackResult PMMultipleOwnerDeviceDiscovery(unsigned short waittime, bool isMul
     return res;
 }
 
+/**
+ * The function is responsible for determining if the caller is a subowner of the specified device.
+ *
+ * @param[in] device       MOT enabled device that contains a list of subowners
+ * @param[out] isSubowner  Bool indicating whether the caller is a subowner of device
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PMIsSubownerOfDevice(OCProvisionDev_t *device, bool *isSubowner)
+{  
+    if ((NULL == device) || (NULL == isSubowner))
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OicUuid_t myId;
+    memset(&myId, 0, sizeof(myId));
+    OicSecSubOwner_t* subOwner = NULL;
+
+    *isSubowner = false;
+
+    OCStackResult result = GetDoxmDeviceID(&myId);
+    if (OC_STACK_OK == result)
+    {
+        LL_FOREACH(device->doxm->subOwners, subOwner)
+        {
+            if (memcmp(myId.id, subOwner->uuid.id, sizeof(myId.id)) == 0)
+            {
+                *isSubowner = true;
+                break;
+            }
+        }
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "Error while getting my UUID.");
+    }
+
+    return result;
+}
 #endif //MULTIPLE_OWNER
 
 static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
index 504b5a3..0a38ae7 100644 (file)
 #define NUMBER_OF_PINNUM (10)
 #define NUMBER_OF_ALPHABET (26)
 
-static GeneratePinCallback gGenPinCallback = NULL;
-static InputPinCallback gInputPinCallback = NULL;
+/**
+ * Callbacks for displaying a pin.
+ */
+typedef struct DisplayPinCallbacks
+{
+    GeneratePinCallback callback;
+    DisplayPinCallbackWithContext contextCallback;
+    void* context;
+} DisplayPinCallbacks_t;
+
+/**
+ * Callbacks for pin input.
+ */
+typedef struct InputPinCallbacks
+{
+    InputPinCallback callback;
+    InputPinCallbackWithContext contextCallback;
+    void* context;
+} InputPinCallbacks_t;
+
+static DisplayPinCallbacks_t g_displayPinCallbacks = { .callback = NULL, .contextCallback = NULL, .context = NULL };
+static InputPinCallbacks_t g_inputPinCallbacks = { .callback = NULL, .contextCallback = NULL, .context = NULL };
 
 typedef struct PinOxmData {
     uint8_t pinData[OXM_RANDOM_PIN_MAX_SIZE + 1];
@@ -94,8 +114,34 @@ void SetInputPinCB(InputPinCallback pinCB)
         OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
         return;
     }
+    
+    if ((NULL != g_inputPinCallbacks.callback) || (NULL != g_inputPinCallbacks.contextCallback))
+    {
+        OIC_LOG(ERROR, TAG, "Callback for input pin is already set.");
+        return;
+    }
 
-    gInputPinCallback = pinCB;
+    g_inputPinCallbacks.callback = pinCB;
+}
+
+OCStackResult SetInputPinWithContextCB(InputPinCallbackWithContext inputPinCB, void* context)
+{
+    if (NULL == inputPinCB)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
+        return OC_STACK_INVALID_PARAM;
+    }
+    
+    if ((NULL != g_inputPinCallbacks.callback) || (NULL != g_inputPinCallbacks.contextCallback))
+    {
+        OIC_LOG(ERROR, TAG, "Callback for input pin is already set.");
+        return OC_STACK_DUPLICATE_REQUEST;
+    }
+
+    g_inputPinCallbacks.contextCallback = inputPinCB;
+    g_inputPinCallbacks.context = context;
+
+    return OC_STACK_OK;
 }
 
 void SetGeneratePinCB(GeneratePinCallback pinCB)
@@ -106,12 +152,57 @@ void SetGeneratePinCB(GeneratePinCallback pinCB)
         return;
     }
 
-    gGenPinCallback = pinCB;
+    if ((NULL != g_displayPinCallbacks.callback) || (NULL != g_displayPinCallbacks.contextCallback))
+    {
+        OIC_LOG(ERROR, TAG, "Callback for generate pin is already set.");
+        return;
+    }
+
+    g_displayPinCallbacks.callback = pinCB;
+}
+
+OCStackResult SetDisplayPinWithContextCB(DisplayPinCallbackWithContext displayPinCB, void* context)
+{
+    if (NULL == displayPinCB)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to set a callback for displaying a pin.");
+        return OC_STACK_INVALID_PARAM;
+    }
+    
+    if ((NULL != g_displayPinCallbacks.callback) || (NULL != g_displayPinCallbacks.contextCallback))
+    {
+        OIC_LOG(ERROR, TAG, "Callback for displaying a pin is already set.");
+        return OC_STACK_DUPLICATE_REQUEST;
+    }
+
+    g_displayPinCallbacks.contextCallback = displayPinCB;
+    g_displayPinCallbacks.context = context;
+
+    return OC_STACK_OK;
 }
 
 void UnsetInputPinCB()
 {
-    gInputPinCallback = NULL;
+    UnsetInputPinWithContextCB();
+}
+
+void UnsetInputPinWithContextCB()
+{
+    g_inputPinCallbacks.callback = NULL;
+    g_inputPinCallbacks.contextCallback = NULL;
+    g_inputPinCallbacks.context = NULL;
+}
+
+void UnsetGeneratePinCB()
+{
+    UnsetDisplayPinWithContextCB();
+}
+
+void UnsetDisplayPinWithContextCB()
+{
+    g_displayPinCallbacks.callback = NULL;
+    g_displayPinCallbacks.contextCallback = NULL;
+    g_displayPinCallbacks.context = NULL;
 }
 
 /**
@@ -187,9 +278,13 @@ OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
     pinBuffer[g_PinOxmData.pinSize] = '\0';
     g_PinOxmData.pinData[g_PinOxmData.pinSize] = '\0';
 
-    if(gGenPinCallback)
+    if(g_displayPinCallbacks.callback)
     {
-        gGenPinCallback(pinBuffer, g_PinOxmData.pinSize);
+        g_displayPinCallbacks.callback(pinBuffer, g_PinOxmData.pinSize);
+    }
+    else if (g_displayPinCallbacks.contextCallback)
+    {
+        g_displayPinCallbacks.contextCallback(pinBuffer, g_PinOxmData.pinSize, g_displayPinCallbacks.context);
     }
     else
     {
@@ -223,7 +318,7 @@ OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
     return OC_STACK_OK;
 }
 
-OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
+OCStackResult InputPin(OicUuid_t deviceId, char* pinBuffer, size_t bufferSize)
 {
     if(!pinBuffer)
     {
@@ -236,9 +331,15 @@ OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
         return OC_STACK_INVALID_PARAM;
     }
 
-    if(gInputPinCallback)
+    if(g_inputPinCallbacks.callback)
+    {
+        g_inputPinCallbacks.callback(pinBuffer, bufferSize);
+        OICStrcpy((char*)(g_PinOxmData.pinData), OXM_RANDOM_PIN_MAX_SIZE + 1, pinBuffer);
+        g_PinOxmData.pinSize = strlen((char*)(g_PinOxmData.pinData));
+    }
+    else if (g_inputPinCallbacks.contextCallback)
     {
-        gInputPinCallback(pinBuffer, bufferSize);
+        g_inputPinCallbacks.contextCallback(deviceId, pinBuffer, bufferSize, g_inputPinCallbacks.context);
         OICStrcpy((char*)(g_PinOxmData.pinData), OXM_RANDOM_PIN_MAX_SIZE + 1, pinBuffer);
         g_PinOxmData.pinSize = strlen((char*)(g_PinOxmData.pinData));
     }
index 0bc1dbf..f0967c7 100644 (file)
@@ -41,6 +41,8 @@ namespace OC
             size_t chainSize)>CertChainCallBack;
     typedef std::function<OCStackResult(uint8_t verifNum[])> DisplayNumCB;
     typedef std::function<OCStackResult()> UserConfirmNumCB;
+    typedef std::function<void(char* pinData, size_t pinSize)> DisplayPinCB;
+    typedef std::function<void(OicUuid_t deviceId, char* pinBuffer, size_t pinBufferSize)> InputPinCB;
 
     struct ProvisionContext
     {
@@ -54,6 +56,18 @@ namespace OC
         TrustCertChainContext(CertChainCallBack cb) : callback(cb){}
     };
 
+    struct DisplayPinContext
+    {
+        DisplayPinCB callback;
+        DisplayPinContext(DisplayPinCB cb) : callback(cb) {}
+    };
+
+    struct InputPinContext
+    {
+        InputPinCB callback;
+        InputPinContext(InputPinCB cb) : callback(cb) {}
+    };
+
     struct DisplayNumContext
     {
         DisplayNumCB callback;
@@ -66,6 +80,9 @@ namespace OC
         UserConfirmNumContext(UserConfirmNumCB cb) : callback(cb){}
     };
 
+    typedef InputPinContext* InputPinCallbackHandle;
+    typedef DisplayPinContext* DisplayPinCallbackHandle;
+
     /**
      * This class is for credential's to be set to devices.
      * The types supported are
@@ -227,24 +244,116 @@ namespace OC
             static OCStackResult discoverMultipleOwnedDevices(unsigned short timeout,
                     DeviceList_t &list);
 
+            /**
+             * API is responsible for discovery of a MOT enabled device with a specified deviceID.
+             * The function will return when security information for device with deviceID has been
+             * obtained or the timeout has been exceeded.
+             *
+             * @param timeout      Maximum time, in seconds, this function will listen for responses
+             *                     from servers before returning.
+             * @param deviceID     deviceID of target device
+             * @param foundDevice  OCSecureResource object of found device.
+             * @return ::OC_STACK_OK in case of success and other value otherwise.
+             *         ::OC_STACK_INVALID_PARAM when deviceID is NULL or ppFoundDevice is not
+             *                                  initailized.
+             */
+            static OCStackResult discoverMultipleOwnerEnabledDevice(unsigned short timeout,
+                    const OicUuid_t* deviceID,
+                    std::shared_ptr<OCSecureResource> &foundDevice);
+
 #endif
 
             /**
-             * API for registering Pin Callback.
+             * API for registering a pin input callback. Only one input pin callback is allowed
+             * to be registered at a time by setInputPinCallback and registerInputPinCallback. 
+             * Use unsetInputPinCallback to unregister a callback set by setInputPinCallback. 
              *
-             * @param InputPinCallback inputPin caaback function.
-             * @return ::OC_STACK_OK in case of success and other value otherwise.
+             * @deprecated Use registerInputPinCallback instead.
+             *
+             * @param InputPinCallback inputPin callback function.
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             *         OC_STACK_INVALID_CALLBACK if inputPin is invalid.
+             *         OC_STACK_DUPLICATE_REQUEST if an input pin callback has already been set.
              */
             static OCStackResult setInputPinCallback(InputPinCallback inputPin);
 
             /**
-             * API for de-registering Pin Callback.
+             * API for de-registering a pin callback.
+             *
+             * @deprecated Use deregisterInputPinCallback instead.
              *
              * @return ::OC_STACK_OK in case of success and other value otherwise.
              */
             static OCStackResult unsetInputPinCallback();
 
             /**
+             * API to register for a callback to input a pin. Only one input pin callback is allowed
+             * to be registered at a time by setInputPinCallback and registerInputPinCallback. Use 
+             * deregisterInputPinCallback to unregister a callback set by registerInputPinCallback.
+             *
+             * @param inputPinCB             Callback which is to be registered.
+             * @param inputPinCallbackHandle Pointer to a handle that can be used to deregister the callback.
+             * @return  OC_STACK_OK in case of success and other values otherwise.
+             *          OC_STACK_INVALID_CALLBACK if inputPinCB is invalid.
+             *          OC_STACK_INVALID_PARAM if inputPinCallbackHandle is invalid.
+             *          OC_STACK_DUPLICATE_REQUEST if an input pin callback has already been set.
+             */
+            static OCStackResult registerInputPinCallback(InputPinCB inputPinCB, InputPinCallbackHandle* inputPinCallbackHandle);
+
+            /**
+             * API to de-register the callback to input a pin.
+             *
+             * @param inputPinCallbackHandle Handle specifying which callback to deregister.
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             */
+            static OCStackResult deregisterInputPinCallback(InputPinCallbackHandle inputPinCallbackHandle);
+
+            /**
+             * API to register a callback to display the stack generated PIN. Only one display pin callback
+             * is allowed to be registered at a time by setDisplayPinCB and registerDisplayPinCallback.
+             * Use unsetDisplayPinCB to unregister a callback set by setDisplayPinCB.
+             *
+             * @deprecated Use registerDisplayPinCallback instead.
+             *
+             * @param displayPin Callback method to display a generated pin.
+             * @return OC_STACK_OK in case of success and other value otherwise.
+             *         OC_STACK_INVALID_CALLBACK if displayPin is invalid.
+             *         OC_STACK_DUPLICATE_REQUEST if a display pin callback has already been set.
+             */
+            static OCStackResult setDisplayPinCB(GeneratePinCallback displayPin);
+
+            /**
+             * API for de-registering the display pin callback.
+             *
+             * @deprecated Use deregisterDisplayPinCallback instead.
+             *
+             * @return ::OC_STACK_OK in case of success and other value otherwise.
+             */
+            static OCStackResult unsetDisplayPinCB();
+
+            /**
+             * API to register for a callback to display a pin. Only one display pin callback is
+             * allowed to be registered at a time by setDisplayPinCB and registerDisplayPinCallback.
+             * Use deregisterDisplayPinCallback to unregister a callback set by registerDisplayPinCallback.
+             *
+             * @param displayPinCB             Callback which is to be registered.
+             * @param displayPinCallbackHandle Pointer to a handle that can be used to deregister the callback.
+             * @return  OC_STACK_OK in case of success and other value otherwise.
+             *          OC_STACK_INVALID_CALLBACK if displayPinCB is invalid.
+             *          OC_STACK_INVALID_PARAM if displayPinCallbackHandle is invalid.
+             *          OC_STACK_DUPLICATE_REQUEST if a display pin callback has already been set.
+             */
+            static OCStackResult registerDisplayPinCallback(DisplayPinCB displayPinCB, DisplayPinCallbackHandle* displayPinCallbackHandle);
+
+            /**
+             * API to de-register the callback to display a pin.
+             *
+             * @param displayPinCallbackHandle Handle used to deregister the callback.
+             * @return  OC_STACK_OK in case of success and other value otherwise.
+             */
+            static OCStackResult deregisterDisplayPinCallback(DisplayPinCallbackHandle displayPinCallbackHandle);
+
+            /**
              * API to get status of all the devices in current subnet. The status include endpoint
              * information and doxm information which can be extracted during owned and unowned
              * discovery. Along with this information, API will provide information about
@@ -260,13 +369,6 @@ namespace OC
             static OCStackResult getDevInfoFromNetwork(unsigned short timeout,
                     DeviceList_t &ownedDevList,
                     DeviceList_t &unownedDevList);
-            /**
-             * Server API to register callback to display stack generated PIN.
-             *
-             * @param displayPin Callback Method to Display generated PIN.
-             * @return ::OC_STACK_OK in case of success and other value otherwise.
-             */
-            static OCStackResult setDisplayPinCB(GeneratePinCallback displayPin);
 
             /**
              * API to remove device credential and ACL from all devices in subnet.
@@ -560,6 +662,12 @@ namespace OC
             bool getOwnedStatus();
 
             /**
+             * This function provides the selected ownership transfer method of the device.
+             * @return Selected ownership transfer method.
+             */
+            OicSecOxm_t getSelectedOwnershipTransferMethod();
+
+            /**
              * API to get the proper OxM for OT.
              *
              * @param oxm Address to save the selected OxM.
@@ -629,6 +737,15 @@ namespace OC
             OCStackResult doMultipleOwnershipTransfer(ResultCallBack resultCallback);
 
             /**
+             * API to check if the caller is a subowner of the MOT device.
+             *
+             * @param subowner  Bool indicating if the caller is a subowner.
+             *
+             * @return ::OC_STACK_OK in case of success and other values otherwise.
+             */
+            OCStackResult isSubownerOfDevice(bool* subowner);
+
+            /**
              * API to get the proper OxM for MOT.
              *
              * @param oxm Address to save the selected OxM.
@@ -651,7 +768,6 @@ namespace OC
              */
             bool isMOTEnabled();
 
-
 #endif // MULTIPLE_OWNER
 
         private:
index ac68190..66a530c 100644 (file)
 
 Import('env')
 
-ocprovision_env = env.Clone()
+lib_env = env.Clone()
+SConscript(lib_env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+ocprovision_env = lib_env.Clone()
 
 ######################################################################
 # Build flags
@@ -66,6 +69,13 @@ if target_os in ['darwin', 'ios']:
        ocprovision_env.AppendUnique(LIBPATH = [ocprovision_env.get('BUILD_DIR')])
        ocprovision_env.AppendUnique(LIBS = ['octbstack', 'oc_logger'])
 
+if target_os in ['windows']:
+       ocprovision_env.PrependUnique(LIBS = [
+        'oc',
+        'octbstack',
+        'oc_logger',
+        ])
+
 ######################################################################
 # Source files and Targets
 ######################################################################
@@ -79,7 +89,10 @@ if ocprovision_env.get('WITH_TCP') == True:
        ]
         ocprovision_env.UserInstallTargetHeader('../include/OCCloudProvisioning.hpp', 'resource', 'OCCloudProvisioning.hpp')
 
-ocprovision = ocprovision_env.SharedLibrary('ocprovision', ocprovision_src)
+if target_os not in ['windows']:
+    ocprovision = ocprovision_env.SharedLibrary('ocprovision', ocprovision_src)
+else:
+    ocprovision = ocprovision_env.StaticLibrary('ocprovision', ocprovision_src)
 ocprovision_env.InstallTarget(ocprovision, 'libocprovision')
 ocprovision_env.UserInstallTargetLib(ocprovision, 'libocprovision')
 ocprovision_env.UserInstallTargetHeader('../include/OCProvisioningManager.hpp', 'resource', 'OCProvisioningManager.hpp')
index 1408167..6a4e9f5 100644 (file)
@@ -113,7 +113,7 @@ void moveTransferredDevice()
     pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
 }
 
-void InputPinCB(char* pinBuf, size_t bufSize)
+void OnInputPinCB(OicUuid_t deviceId, char* pinBuf, size_t bufSize)
 {
     if(pinBuf)
     {
@@ -853,7 +853,6 @@ OCStackResult confirmMutualVerifNumCB(void)
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 static int saveTrustCert(void)
 {
-
     // call |OCSaveTrustCertChainBin| API actually
     printf("   Save Trust Cert. Chain into Cred of SVR.\n");
 
@@ -937,6 +936,7 @@ int main(void)
 
     try
     {
+        InputPinCallbackHandle callbackHandle = nullptr;
         int choice;
         OicSecAcl_t *acl1 = nullptr, *acl2 = nullptr;
         if (OCSecure::provisionInit("") != OC_STACK_OK)
@@ -945,6 +945,12 @@ int main(void)
             return 1;
         }
 
+        result = OCSecure::registerInputPinCallback(OnInputPinCB, &callbackHandle);
+        if (result != OC_STACK_OK)
+        {
+            std::cout << "!!Error - registerInputPinCallback failed." << std::endl;
+        }
+
         result = OCSecure::registerDisplayNumCallback(displayMutualVerifNumCB);
         if (result != OC_STACK_OK)
         {
@@ -1049,11 +1055,7 @@ int main(void)
                             break;
                         }
                         transferDevIdx = devNum - 1;
-
-                        //register callbacks for JUST WORKS and PIN methods
-                        std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
-                        OCSecure::setInputPinCallback(InputPinCB);
-
+                    
                         ask = 0;
                         std::cout << "Transfering ownership for : "<<
                             pUnownedDevList[devNum-1]->getDeviceID()<<std::endl;
@@ -1663,6 +1665,9 @@ int main(void)
                     break;
             }
         }
+
+        // Unregister the input pin callback
+        OCSecure::deregisterInputPinCallback(callbackHandle);
     }
     catch(OCException& e)
     {
index a2b37e8..f662526 100644 (file)
@@ -86,7 +86,7 @@ void moveTransferredDevice()
     pMOTEnabledDeviceList.erase(pMOTEnabledDeviceList.begin() + transferDevIdx);
 }
 
-void InputPinCB(char* pinBuf, size_t bufSize)
+void OnInputPinCB(OicUuid_t deviceId, char* pinBuf, size_t bufSize)
 {
     if(pinBuf)
     {
@@ -184,6 +184,8 @@ void putCallback(const HeaderOptions& /*headerOptions*/, const OCRepresentation&
 
 int main(void)
 {
+    InputPinCallbackHandle callbackHandle = nullptr;
+
     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
 
     // Create PlatformConfig object
@@ -198,8 +200,11 @@ int main(void)
 
     OCPlatform::Configure(cfg);
 
-    //set Input Pin callback
-    OCSecure::setInputPinCallback(InputPinCB);
+    // Set Input Pin callback
+    if (OC_STACK_OK != OCSecure::registerInputPinCallback(OnInputPinCB, &callbackHandle))
+    {
+        std::cout << "!!Error - registerInputPinCallback failed." << std::endl;
+    }
 
     try
     {
@@ -390,5 +395,8 @@ int main(void)
         oclog() << "Exception in main: "<<e.what();
     }
 
+    // Unregister input pin callback
+    OCSecure::deregisterInputPinCallback(callbackHandle);
+
     return 0;
 }
index fe0e31c..fd4f127 100644 (file)
 
 namespace OC
 {
+    /**
+     * Prevent multiple registrations of the input pin callback since the 
+     * underlying IoTivity stack can only handle having one callback set
+     * at a time.
+     */
+    bool g_inputPinCallbackRegistered = false;
+
+    /**
+     * Prevent multiple registrations of the display pin callback since the
+     * underlying IoTivity stack can only handle having one callback set
+     * at a time.
+     */
+    bool g_displayPinCallbackRegistered = false;
+
     OCStackResult OCSecure::provisionInit(const std::string& dbPath)
     {
         OCStackResult result;
@@ -280,17 +294,65 @@ namespace OC
         return result;
     }
 
+    OCStackResult OCSecure::discoverMultipleOwnerEnabledDevice(unsigned short timeout, const OicUuid_t* deviceID, std::shared_ptr<OCSecureResource> &foundDevice)
+    {
+        OCStackResult result;
+        OCProvisionDev_t *pDev = nullptr;
+        auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+        auto cLock = csdkLock.lock();
+
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCDiscoverMultipleOwnerEnabledSingleDevice(timeout, deviceID, &pDev);
+            if (result == OC_STACK_OK)
+            {
+                if (pDev)
+                {
+                    foundDevice.reset(new OCSecureResource(csdkLock, pDev));
+                }
+                else
+                {
+                    oclog() << "Not found Secure resource!";
+                    foundDevice.reset();
+                }
+            }
+            else
+            {
+                oclog() << "Secure resource discovery failed!";
+            }
+        }
+        else
+        {
+            oclog() << "Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+    }
+
 #endif
     OCStackResult OCSecure::setInputPinCallback(InputPinCallback inputPin)
     {
-        OCStackResult result;
+        if (!inputPin)
+        {
+            oclog() << "inputPin can't be null";
+            return OC_STACK_INVALID_PARAM;
+        }
+        else if (g_inputPinCallbackRegistered)
+        {
+            oclog() << "Callback for pin input already registered.";
+            return OC_STACK_DUPLICATE_REQUEST;
+        }
+
+        OCStackResult result = OC_STACK_OK;
         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
 
         if (cLock)
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
             SetInputPinCB(inputPin);
-            result = OC_STACK_OK;
+            g_inputPinCallbackRegistered = true;
         }
         else
         {
@@ -303,18 +365,104 @@ namespace OC
 
     OCStackResult OCSecure::unsetInputPinCallback()
     {
-        OCStackResult result;
+        OCStackResult result = OC_STACK_OK;
         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
 
         if (cLock)
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
             UnsetInputPinCB();
-            result = OC_STACK_OK;
+            g_inputPinCallbackRegistered = false;
         }
         else
         {
-            oclog() <<"Mutex not found";
+            oclog() << "Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+    }
+    
+    static void inputPinCallbackWrapper(OicUuid_t deviceId, char* pinBuffer, size_t pinBufferSize, void* context)
+    {
+        (static_cast<InputPinContext*>(context))->callback(deviceId, pinBuffer, pinBufferSize);
+    }
+
+    OCStackResult OCSecure::registerInputPinCallback(InputPinCB inputPinCB, InputPinCallbackHandle* inputPinCallbackHandle)
+    {
+        OCStackResult result = OC_STACK_ERROR;
+
+        if (!inputPinCB)
+        {
+            oclog() << "Failed to register callback for pin input.";
+            return OC_STACK_INVALID_CALLBACK;
+        }
+        else if (!inputPinCallbackHandle)
+        {
+            return OC_STACK_INVALID_PARAM;
+        }
+        else if (g_inputPinCallbackRegistered)
+        {
+            oclog() << "Callback for pin input already registered.";
+            return OC_STACK_DUPLICATE_REQUEST;
+        }
+
+        *inputPinCallbackHandle = nullptr;
+
+        auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+        if (cLock)
+        {
+            InputPinContext* inputPinContext = new InputPinContext(inputPinCB);
+            if (nullptr != inputPinContext)
+            {
+                std::lock_guard<std::recursive_mutex> lock(*cLock);
+                result = SetInputPinWithContextCB(&inputPinCallbackWrapper, static_cast<void*>(inputPinContext));
+                if (OC_STACK_OK == result)
+                {
+                    g_inputPinCallbackRegistered = true;
+                    *inputPinCallbackHandle = inputPinContext;
+                }
+                else
+                {
+                    if (nullptr != inputPinContext)
+                    {
+                        delete inputPinContext;
+                    }
+                }
+            }
+            else
+            {
+                result = OC_STACK_NO_MEMORY;
+            }
+        }
+        else
+        {
+            oclog() << "Mutex not found";
+        }
+
+        return result;
+    }
+
+    OCStackResult OCSecure::deregisterInputPinCallback(InputPinCallbackHandle inputPinCallbackHandle)
+    {
+        OCStackResult result = OC_STACK_OK;
+
+        auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            UnsetInputPinWithContextCB();
+            if (nullptr != inputPinCallbackHandle)
+            {
+                delete inputPinCallbackHandle;
+            }
+            g_inputPinCallbackRegistered = false;
+        }
+        else
+        {
+            oclog() << "Mutex not found";
             result = OC_STACK_ERROR;
         }
 
@@ -375,6 +523,11 @@ namespace OC
             oclog() <<"displayPin can't be null";
             return OC_STACK_INVALID_PARAM;
         }
+        else if (g_displayPinCallbackRegistered)
+        {
+            oclog() << "Callback for pin display already registered.";
+            return OC_STACK_DUPLICATE_REQUEST;
+        }
 
         OCStackResult result = OC_STACK_OK;
         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
@@ -383,6 +536,7 @@ namespace OC
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
             SetGeneratePinCB(displayPin);
+            g_displayPinCallbackRegistered = true;
         }
         else
         {
@@ -393,6 +547,111 @@ namespace OC
         return result;
     }
 
+    OCStackResult OCSecure::unsetDisplayPinCB()
+    {
+        OCStackResult result = OC_STACK_OK;
+        auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            UnsetGeneratePinCB();
+            g_displayPinCallbackRegistered = false;
+        }
+        else
+        {
+            oclog() << "Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+    }
+
+    static void displayPinCallbackWrapper(char* pinData, size_t pinDataSize, void* context)
+    {
+        (static_cast<DisplayPinContext*>(context))->callback(pinData, pinDataSize);
+    }
+
+    OCStackResult OCSecure::registerDisplayPinCallback(DisplayPinCB displayPinCB, DisplayPinCallbackHandle* displayPinCallbackHandle)
+    {
+        OCStackResult result = OC_STACK_ERROR;
+
+        if (!displayPinCB)
+        {
+            oclog() << "Failed to register callback for pin display.";
+            return OC_STACK_INVALID_CALLBACK;
+        }
+        else if (!displayPinCallbackHandle)
+        {
+            return OC_STACK_INVALID_PARAM;
+        }
+        else if (g_displayPinCallbackRegistered)
+        {
+            oclog() << "Callback for pin display already registered.";
+            return OC_STACK_DUPLICATE_REQUEST;
+        }
+
+        *displayPinCallbackHandle = nullptr;
+
+        auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+        if (cLock)
+        {
+            DisplayPinContext* displayPinContext = new DisplayPinContext(displayPinCB);
+            if (nullptr != displayPinContext)
+            {
+                std::lock_guard<std::recursive_mutex> lock(*cLock);
+                result = SetDisplayPinWithContextCB(&displayPinCallbackWrapper, static_cast<void*>(displayPinContext));
+                if (OC_STACK_OK == result)
+                {
+                    *displayPinCallbackHandle = displayPinContext;
+                    g_displayPinCallbackRegistered = true;
+                }
+                else
+                {
+                    if (nullptr != displayPinContext)
+                    {
+                        delete displayPinContext;
+                    }
+                }
+            }
+            else
+            {
+                result = OC_STACK_NO_MEMORY;
+            }
+        }
+        else
+        {
+            oclog() << "Mutex not found";
+        }
+
+        return result;
+    }
+
+    OCStackResult OCSecure::deregisterDisplayPinCallback(DisplayPinCallbackHandle displayPinCallbackHandle)
+    {
+        OCStackResult result = OC_STACK_OK;
+
+        auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            UnsetDisplayPinWithContextCB();
+            if (nullptr != displayPinCallbackHandle)
+            {
+                delete displayPinCallbackHandle;
+            }
+            g_displayPinCallbackRegistered = false;
+        }
+        else
+        {
+            oclog() << "Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+
+        return result;
+    }
+
     OCStackResult OCSecure::removeDeviceWithUuid(unsigned short waitTimeForOwnedDeviceDiscovery,
             std::string uuid,
             ResultCallBack resultCallback)
@@ -813,6 +1072,30 @@ namespace OC
         return result;
     }
 
+    OCStackResult OCSecureResource::isSubownerOfDevice(bool* subowner)
+    {
+        if (!subowner)
+        {
+            oclog() << "Subowner cannot be null";
+            return OC_STACK_INVALID_CALLBACK;
+        }
+
+        OCStackResult result;
+        auto cLock = m_csdkLock.lock();
+
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCIsSubownerOfDevice(devPtr, subowner);
+        }
+        else
+        {
+            oclog() << "Mutex not found";
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
 #endif
     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
             ResultCallBack resultCallback)
@@ -1113,6 +1396,12 @@ namespace OC
         return devPtr->doxm->owned;
     }
 
+    OicSecOxm_t OCSecureResource::getSelectedOwnershipTransferMethod()
+    {
+        validateSecureResource();
+        return devPtr->doxm->oxmSel;
+    }
+
     void OCSecureResource::validateSecureResource()
     {
         if (!devPtr)
index 6545707..0883838 100644 (file)
@@ -161,5 +161,5 @@ if with_cloud:
        oclib_env.UserInstallTargetHeader(header_dir + 'OCAccountManager.h', 'resource', 'OCAccountManager.h')
 
 # Add Provisioning library
-if target_os in ['linux', 'android', 'tizen'] and secured == '1':
+if target_os in ['linux', 'android', 'tizen', 'windows'] and secured == '1':
         SConscript('../provisioning/SConscript')
diff --git a/run.bat b/run.bat
index 280000c..34305c8 100644 (file)
--- a/run.bat
+++ b/run.bat
@@ -38,6 +38,7 @@ set ROUTING=EP
 set WITH_TCP=1
 set WITH_UPSTREAM_LIBCOAP=1
 set BINDIR=debug
+set MULTIPLE_OWNER=1
 
 set RUN_ARG=%1
 SHIFT
@@ -80,7 +81,7 @@ IF "%BUILD_MSYS%" == "" (
   set PATH=!PATH!;!BUILD_DIR!;C:\msys64\mingw64\bin
 )
 
-set BUILD_OPTIONS= TARGET_OS=%TARGET_OS% TARGET_ARCH=%TARGET_ARCH% RELEASE=%RELEASE% WITH_RA=0 TARGET_TRANSPORT=IP SECURED=%SECURED% WITH_TCP=%WITH_TCP% BUILD_SAMPLE=ON LOGGING=%LOGGING% TEST=%TEST% RD_MODE=CLIENT ROUTING=%ROUTING% WITH_UPSTREAM_LIBCOAP=%WITH_UPSTREAM_LIBCOAP%
+set BUILD_OPTIONS= TARGET_OS=%TARGET_OS% TARGET_ARCH=%TARGET_ARCH% RELEASE=%RELEASE% WITH_RA=0 TARGET_TRANSPORT=IP SECURED=%SECURED% WITH_TCP=%WITH_TCP% BUILD_SAMPLE=ON LOGGING=%LOGGING% TEST=%TEST% RD_MODE=CLIENT ROUTING=%ROUTING% WITH_UPSTREAM_LIBCOAP=%WITH_UPSTREAM_LIBCOAP% MULTIPLE_OWNER=%MULTIPLE_OWNER%
 
 REM Use MSVC_VERSION=12.0 for VS2013, or MSVC_VERSION=14.0 for VS2015.
 REM If MSVC_VERSION has not been defined here, SCons chooses automatically a VS version.
@@ -145,6 +146,7 @@ if "!RUN_ARG!"=="server" (
   echo   ROUTING=%ROUTING%
   echo   WITH_TCP=%WITH_TCP%
   echo   WITH_UPSTREAM_LIBCOAP=%WITH_UPSTREAM_LIBCOAP%
+  echo   MULTIPLE_OWNER=%MULTIPLE_OWNER%
   echo   MSVC_VERSION=%MSVC_VERSION%
   echo.scons VERBOSE=1 %BUILD_OPTIONS%
   scons VERBOSE=1 %BUILD_OPTIONS%