Update the OTMContext management mechanism to improve the reliability of the OTM...
authorChul Lee <chuls.lee@samsung.com>
Mon, 31 Oct 2016 03:02:30 +0000 (12:02 +0900)
committerRandeep Singh <randeep.s@samsung.com>
Wed, 9 Nov 2016 08:54:15 +0000 (08:54 +0000)
  1. Apply the list mechanism to manage the OTMContext.
    -> It replaces the global variables of OTMContext.

  2. Add the OCDoHandle member into OTMContext.
    -> In case of OTM process stopped before OTM process complete,
       unnecessary retransmission can be occur
       due to request is performed just before the OTM process stops.
       So we need to cancel this request to prevent retransmission.
       OCDoHandle will be used at this time.

  3. Add the device status of PDM to prevent duplicate OTM.
    -> Added PDM_DEVICE_INIT to prevent deplicate OTM.
       If device status is PDM_DEVICE_INIT, PT will skip OTM process of this device.

Change-Id: I74e200aa88a0c5016c065a518b75614bf4a3a7a8
Signed-off-by: Chul Lee <chuls.lee@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/13857
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Kevin Kane <kkane@microsoft.com>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
(cherry picked from commit 77b6057600843dab97b1af64f31c6aacd5a9b32c)
Reviewed-on: https://gerrit.iotivity.org/gerrit/14143

12 files changed:
resource/csdk/security/provisioning/SConscript
resource/csdk/security/provisioning/include/internal/otmcontextlist.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h
resource/csdk/security/provisioning/include/internal/provisioningdatabasemanager.h
resource/csdk/security/provisioning/src/multipleownershiptransfermanager.c
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/otmcontextlist.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/provisioning/src/provisioningdatabasemanager.c
resource/csdk/security/provisioning/unittest/provisioningdatabasemanager.cpp
resource/csdk/security/src/aclresource.c
resource/csdk/security/src/doxmresource.c

index 043df1b..44a9151 100644 (file)
@@ -98,6 +98,7 @@ if provisioning_env.get('MULTIPLE_OWNER') == '1':
 provisioning_src = [
        'src/pmutility.c',
        'src/credentialgenerator.c',
+       'src/otmcontextlist.c',
        'src/ownershiptransfermanager.c',
        'src/secureresourceprovider.c',
        'src/ocprovisioningmanager.c',
diff --git a/resource/csdk/security/provisioning/include/internal/otmcontextlist.h b/resource/csdk/security/provisioning/include/internal/otmcontextlist.h
new file mode 100644 (file)
index 0000000..81e92f8
--- /dev/null
@@ -0,0 +1,74 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#ifndef _OTM_CONTEXT_LIST_H_
+#define _OTM_CONTEXT_LIST_H_
+
+#include "pmtypes.h"
+#include "ocstack.h"
+#include "octypes.h"
+#include "securevirtualresourcetypes.h"
+#include "ownershiptransfermanager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef struct OTMContextItem {
+    OTMContext_t* otmCtx;
+    OCDevAddr endpoint;
+    struct OTMContextItem* next;
+}OTMContextItem_t;
+
+/**
+ * API to remove OTMContext from OTMContext list.
+ *
+ * @param[in] addr IP address of peer
+ * @param[in] port secure port number of peer
+ */
+void RemoveOTMContext(const char* addr, uint16_t port);
+
+/**
+ * API to add OTMContext to OTMContext list.
+ * If same OTMContext exist, will be ignored.
+ *
+ * @param[in] ctx new OTMContext
+ * @param[in] addr IP address of peer
+ * @param[in] port secure port number of peer
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult AddOTMContext(OTMContext_t* ctx, const char* addr, uint16_t port);
+
+/**
+ * API to read OTMContext from OTMContext list
+ *
+ * @param[in] addr IP address of peer
+ * @param[in] port secure port number of peer
+ *
+ * @return OTMContext in case of context found, otherwise NULL.
+ */
+const OTMContext_t* GetOTMContext(const char* addr, uint16_t port);
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+#endif //_OTM_CONTEXT_LIST_H_
\ No newline at end of file
index 7d85cfb..f302bd6 100644 (file)
@@ -55,7 +55,6 @@ OCStackResult OTMDoOwnershipTransfer(void* ctx,
  */\r
 typedef OCStackResult (*OTMLoadSecret)(OTMContext_t* otmCtx);\r
 \r
-\r
 /*\r
  * Callback for create secure channel using secret inputed from OTMLoadSecret callback\r
  */\r
@@ -89,6 +88,7 @@ struct OTMContext{
     OCProvisionResult_t* ctxResultArray;      /**< Result array having result of all device. */\r
     size_t ctxResultArraySize;                /**< No of elements in result array. */\r
     bool ctxHasError;                         /**< Does OT process have any error. */\r
+    OCDoHandle ocDoHandle;                    /** <A handle for latest request message*/\r
     OTMCallbackData_t otmCallback; /**< OTM callbacks to perform the OT/MOT. **/\r
     int attemptCnt;\r
 };\r
index c7c9483..e0dc2b0 100644 (file)
 extern "C" {
 #endif
 
+typedef enum PdmDeviceState {
+    PDM_DEVICE_ACTIVE = 0,
+    PDM_DEVICE_STALE = 1,
+    PDM_DEVICE_INIT = 2,
+    PDM_DEVICE_UNKNOWN = 99
+}PdmDeviceState_t;
 
 /**
  * This method is used by provisioning manager to open provisioning database.
@@ -39,14 +45,24 @@ extern "C" {
 OCStackResult PDMInit(const char* dbPath);
 
 /**
- * This method is used by provisioning manager to check whether device is stale or not with PDM.
+ * This method is used by provisioning manager to check device status.
  *
  * @param[in] uuid information about the target device's uuid.
- * @param[out] result true in case device is stale.
+ * @param[out] result device status.
  *
  * @return OC_STACK_OK in case of success and other value otherwise.
  */
-OCStackResult PDMIsDeviceStale(const OicUuid_t *uuid, bool *result);
+OCStackResult PDMGetDeviceState(const OicUuid_t* uuid, PdmDeviceState_t* result);
+
+/**
+ * This method is used by provisioning manager to update device status.
+ *
+ * @param[in] uuid id of device.
+ * @param[in] state device state. (ref. PdmDeviceState_t)
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMSetDeviceState(const OicUuid_t* uuid, PdmDeviceState_t state);
 
 /**
  * This method is used by provisioning manager to check duplication of device's Device ID with
@@ -130,15 +146,6 @@ OCStackResult PDMGetLinkedDevices(const OicUuid_t* uuidOfDevice, OCUuidList_t**
 OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2);
 
 /**
- * This method is used by provisioning manager to update device status as stale.
- *
- * @param[in] uuidOfDevice id of stale device.
- *
- * @return OC_STACK_OK in case of success and other value otherwise.
- */
-OCStackResult PDMSetDeviceStale(const OicUuid_t* uuidOfDevice);
-
-/**
  * This method is used by provisioning manager to get stale devices.
  *
  * @note in case of sqllite, the caller should set NULL for parameters.
index 09ed4b4..5248ce4 100644 (file)
@@ -58,6 +58,7 @@
 #include "oxmjustworks.h"
 #include "oxmpreconfpin.h"
 #include "oxmrandompin.h"
+#include "otmcontextlist.h"
 
 #define TAG "OIC_MULTIPLE_OTM"
 
  **********************************************************************/
 
 /**
- * Structure to carry SuperOwner's multiple ownership transfer API data to callback.
- */
-typedef struct MOTContext MOTContext_t;
-struct MOTContext
-{
-    void *ctx;                                  /**< Pointer to user context.**/
-    const OCProvisionDev_t *deviceInfo;         /**< Pointer to OCProvisionDev_t.**/
-    OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
-    OCProvisionResult_t *resArr;                /**< Result array.**/
-    int numOfResults;                           /**< Number of results in result array.**/
-    bool hasError;                              /**< Does MOT API have any error.. **/
-};
-
-/**
  * Callback handler of security resource's POST request.
  *
  * @param[in] ctx             ctx value passed to callback from calling function.
@@ -93,38 +80,41 @@ static OCStackApplicationResult MOTUpdateSecurityResourceCB(void *ctx, OCDoHandl
 {
     OIC_LOG_V(INFO, TAG, "Inside MOTUpdateMomCB.");
     (void)UNUSED;
-    MOTContext_t *motCtx = (MOTContext_t*)ctx;
+    OTMContext_t *motCtx = (OTMContext_t*)ctx;
     VERIFY_NON_NULL(TAG, motCtx, ERROR);
-    VERIFY_NON_NULL(TAG, motCtx->resultCallback, ERROR);
-    VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
+    VERIFY_NON_NULL(TAG, motCtx->ctxResultCallback, ERROR);
+    VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
 
     if(clientResponse)
     {
-        memcpy(motCtx->resArr[0].deviceId.id, motCtx->deviceInfo->doxm->deviceID.id, sizeof(OicUuid_t));
-        motCtx->resArr[0].res = clientResponse->result;
+        memcpy(motCtx->ctxResultArray[0].deviceId.id,
+               motCtx->selectedDeviceInfo->doxm->deviceID.id,
+               sizeof(OicUuid_t));
+        motCtx->ctxResultArray[0].res = clientResponse->result;
 
         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
         {
-            motCtx->hasError = false;
+            motCtx->ctxHasError = false;
         }
         else
         {
-            motCtx->hasError = true;
+            motCtx->ctxHasError = true;
         }
     }
     else
     {
         OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
-        motCtx->resArr[0].res = OC_STACK_ERROR;
-        motCtx->hasError = true;
+        motCtx->ctxResultArray[0].res = OC_STACK_ERROR;
+        motCtx->ctxHasError = true;
     }
 
-    motCtx->resultCallback(motCtx->ctx, motCtx->numOfResults, motCtx->resArr, motCtx->hasError);
+    motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
+                              motCtx->ctxResultArray, motCtx->ctxHasError);
 
 exit:
     if(motCtx)
     {
-        OICFree(motCtx->resArr);
+        OICFree(motCtx->ctxResultArray);
         OICFree(motCtx);
     }
     return OC_STACK_DELETE_TRANSACTION;
@@ -140,7 +130,7 @@ static OCStackResult MOTSendPostDoxm(void *ctx,
 {
     OCStackResult postMomRes = OC_STACK_ERROR;
     OCSecurityPayload* secPayload = NULL;
-    MOTContext_t *motCtx = NULL;
+    OTMContext_t *motCtx = NULL;
     bool freeFlag = true;
 
     OIC_LOG(DEBUG, TAG, "IN MOTSendPostDoxm");
@@ -166,15 +156,15 @@ static OCStackResult MOTSendPostDoxm(void *ctx,
     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
 
     //Create the MOT Context to handle the response message
-    motCtx = (MOTContext_t*)OICCalloc(1, sizeof(MOTContext_t));
+    motCtx = (OTMContext_t*)OICCalloc(1, sizeof(OTMContext_t));
     VERIFY_NON_NULL(TAG, motCtx, ERROR);
-    motCtx->deviceInfo = targetDeviceInfo;
-    motCtx->resultCallback = resultCallback;
-    motCtx->numOfResults=1;
-    motCtx->hasError = false;
-    motCtx->ctx = ctx;
-    motCtx->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
-    VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
+    motCtx->selectedDeviceInfo = targetDeviceInfo;
+    motCtx->ctxResultCallback = resultCallback;
+    motCtx->ctxResultArraySize = 1;
+    motCtx->ctxHasError = false;
+    motCtx->userCtx = ctx;
+    motCtx->ctxResultArray= (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
+    VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
 
     //Send POST request
     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
@@ -194,7 +184,7 @@ exit:
     //If POST request successfully sent, motCtx will be cleaned from response handler.
     if(freeFlag && motCtx)
     {
-        OICFree(motCtx->resArr);
+        OICFree(motCtx->ctxResultArray);
         OICFree(motCtx);
     }
 
@@ -387,7 +377,7 @@ OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *target
     OCStackResult postCredRes = OC_STACK_INVALID_CALLBACK;
     bool freeFlag = true;
     OCSecurityPayload* secPayload = NULL;
-    MOTContext_t *motCtx = NULL;
+    OTMContext_t *motCtx = NULL;
     OicSecCred_t* pinCred = NULL;
 
     OIC_LOG(DEBUG, TAG, "IN MOTProvisionPreconfigPIN");
@@ -435,15 +425,15 @@ OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *target
     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
 
     //Create the MOT Context to handle the response message
-    motCtx = (MOTContext_t*)OICCalloc(1, sizeof(MOTContext_t));
+    motCtx = (OTMContext_t*)OICCalloc(1, sizeof(OTMContext_t));
     VERIFY_NON_NULL(TAG, motCtx, ERROR);
-    motCtx->deviceInfo = targetDeviceInfo;
-    motCtx->resultCallback = resultCallback;
-    motCtx->numOfResults=1;
-    motCtx->hasError = false;
-    motCtx->ctx = ctx;
-    motCtx->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
-    VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
+    motCtx->selectedDeviceInfo= targetDeviceInfo;
+    motCtx->ctxResultCallback = resultCallback;
+    motCtx->ctxResultArraySize =1;
+    motCtx->ctxHasError = false;
+    motCtx->userCtx = ctx;
+    motCtx->ctxResultArray = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
+    VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
 
     //Send POST request
     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
@@ -465,7 +455,7 @@ exit:
     //If POST request successfully sent, motCtx will be cleaned from response handler.
     if(freeFlag && motCtx)
     {
-        OICFree(motCtx->resArr);
+        OICFree(motCtx->ctxResultArray);
         OICFree(motCtx);
     }
     if(pinCred)
@@ -508,7 +498,6 @@ static bool IsComplete(OTMContext_t* otmCtx)
 static void SetMOTResult(OTMContext_t* motCtx, const OCStackResult res)
 {
     OIC_LOG_V(DEBUG, TAG, "IN SetMOTResult : %d ", res);
-
     VERIFY_NON_NULL(TAG, motCtx, ERROR);
 
     if(motCtx->selectedDeviceInfo)
@@ -525,6 +514,13 @@ static void SetMOTResult(OTMContext_t* motCtx, const OCStackResult res)
             SetUuidForPinBasedOxm(&emptyUuid);
         }
 
+        OCStackResult pdmRetVal = PDMSetDeviceState(&motCtx->selectedDeviceInfo->doxm->deviceID,
+                                                    PDM_DEVICE_ACTIVE);
+        if (OC_STACK_OK != pdmRetVal)
+        {
+            OIC_LOG_V(ERROR, TAG, "Failed to add device information into PDM_DB : %d", res);
+        }
+
         for(size_t i = 0; i < motCtx->ctxResultArraySize; i++)
         {
             if(memcmp(motCtx->selectedDeviceInfo->doxm->deviceID.id,
@@ -538,7 +534,16 @@ static void SetMOTResult(OTMContext_t* motCtx, const OCStackResult res)
             }
         }
 
-        g_MotCtx = NULL;
+        //Remove the current OTM Context from OTM queue
+        RemoveOTMContext(motCtx->selectedDeviceInfo->endpoint.addr,
+                         motCtx->selectedDeviceInfo->securePort);
+
+        //If there is a request being performed, cancel it to prevent retransmission.
+        if(motCtx->ocDoHandle)
+        {
+            OCCancel(motCtx->ocDoHandle, OC_HIGH_QOS, NULL, 0);
+            motCtx->ocDoHandle = NULL;
+        }
 
         //If all request is completed, invoke the user callback.
         if(IsComplete(motCtx))
@@ -724,7 +729,6 @@ static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle
 
     OIC_LOG(DEBUG, TAG, "IN SubOwnerCredentialHandler");
     (void)UNUSED;
-    OCStackResult res = OC_STACK_ERROR;
     OTMContext_t* motCtx = (OTMContext_t*)ctx;
 
     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
@@ -751,24 +755,14 @@ static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle
                 return OC_STACK_DELETE_TRANSACTION;
             }
 
-            res = PDMAddDevice(&motCtx->selectedDeviceInfo->doxm->deviceID);
-             if (OC_STACK_OK == res)
-             {
-                    OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
-             }
-              else
-             {
-                  OIC_LOG(ERROR, TAG, "MOT is complete but adding information to DB is failed.");
-             }
-
-            SetMOTResult(motCtx, res);
+            SetMOTResult(motCtx, OC_STACK_OK);
         }
     }
     else
     {
-        res = clientResponse->result;
-        OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d", res);
-        SetMOTResult(motCtx, res);
+        OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d",
+                  clientResponse->result);
+        SetMOTResult(motCtx, clientResponse->result);
     }
 
     OIC_LOG(DEBUG, TAG, "OUT SubOwnerCredentialHandler");
@@ -889,84 +883,95 @@ static OCStackResult PostSubOwnerCredential(OTMContext_t* motCtx)
  */
 static void MOTDtlsHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
 {
-    if(NULL != g_MotCtx && NULL != g_MotCtx->selectedDeviceInfo &&
-       NULL != endpoint && NULL != info)
+    OIC_LOG(INFO, TAG, "IN MOTDtlsHandshakeCB");
+
+    if(NULL != endpoint && NULL != info)
     {
         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
                  endpoint->addr, endpoint->port, info->result);
 
-        OicSecDoxm_t* newDevDoxm = g_MotCtx->selectedDeviceInfo->doxm;
-
-        if(NULL != newDevDoxm)
+        OTMContext_t* motCtx = GetOTMContext(endpoint->addr, endpoint->port);
+        if(motCtx)
         {
-            OicUuid_t emptyUuid = {.id={0}};
+            OicSecDoxm_t* newDevDoxm = motCtx->selectedDeviceInfo->doxm;
 
-            //Make sure the address matches.
-            if(strncmp(g_MotCtx->selectedDeviceInfo->endpoint.addr,
-               endpoint->addr,
-               sizeof(endpoint->addr)) == 0 &&
-               g_MotCtx->selectedDeviceInfo->securePort == endpoint->port)
+            if(NULL != newDevDoxm)
             {
-                OCStackResult res = OC_STACK_ERROR;
+                OicUuid_t emptyUuid = {.id={0}};
 
-                //If temporal secure sesstion established successfully
-                if(CA_STATUS_OK == info->result)
+                //Make sure the address matches.
+                if(strncmp(motCtx->selectedDeviceInfo->endpoint.addr,
+                   endpoint->addr,
+                   sizeof(endpoint->addr)) == 0 &&
+                   motCtx->selectedDeviceInfo->securePort == endpoint->port)
                 {
-                    //Delete previous credential such as preconfigured-pin
-                    RemoveCredential(&(g_MotCtx->selectedDeviceInfo->doxm->deviceID));
+                    OCStackResult res = OC_STACK_ERROR;
 
-                    res = SaveSubOwnerPSK(g_MotCtx->selectedDeviceInfo);
-                    if(OC_STACK_OK == res)
+                    //If temporal secure sesstion established successfully
+                    if(CA_STATUS_OK == info->result)
                     {
-                        //POST sub owner credential to new device.
-                        res = PostSubOwnerCredential(g_MotCtx);
-                        if(OC_STACK_OK != res)
+                        //Delete previous credential such as preconfigured-pin
+                        RemoveCredential(&(motCtx->selectedDeviceInfo->doxm->deviceID));
+
+                        res = SaveSubOwnerPSK(motCtx->selectedDeviceInfo);
+                        if(OC_STACK_OK == res)
                         {
-                            OIC_LOG(ERROR, TAG,
-                                    "Failed to send POST request for SubOwner Credential");
-                            SetMOTResult(g_MotCtx, res);
+                            //POST sub owner credential to new device.
+                            res = PostSubOwnerCredential(motCtx);
+                            if(OC_STACK_OK != res)
+                            {
+                                OIC_LOG(ERROR, TAG,
+                                        "Failed to send POST request for SubOwner Credential");
+                                SetMOTResult(motCtx, res);
+                            }
+                        }
+                        else
+                        {
+                            OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
+                            SetMOTResult(motCtx, res);
                         }
                     }
-                    else
-                    {
-                        OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
-                        SetMOTResult(g_MotCtx, res);
-                    }
-                }
-                //In case of authentication failure
-                else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
-                {
-                    //in case of error from wrong PIN, re-start the ownership transfer
-                    if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
+                    //In case of authentication failure
+                    else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
                     {
-                        OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
+                        //in case of error from wrong PIN, re-start the ownership transfer
+                        if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
+                        {
+                            OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
 
-                        g_MotCtx->attemptCnt++;
+                            motCtx->attemptCnt++;
 
-                        if(WRONG_PIN_MAX_ATTEMP > g_MotCtx->attemptCnt)
-                        {
-                            res = StartMultipleOwnershipTransfer(g_MotCtx, g_MotCtx->selectedDeviceInfo);
-                            if(OC_STACK_OK != res)
+                            if(WRONG_PIN_MAX_ATTEMP > motCtx->attemptCnt)
                             {
-                                SetMOTResult(g_MotCtx, res);
-                                OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
+                                res = StartMultipleOwnershipTransfer(motCtx, motCtx->selectedDeviceInfo);
+                                if(OC_STACK_OK != res)
+                                {
+                                    SetMOTResult(motCtx, res);
+                                    OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
+                                }
+                            }
+                            else
+                            {
+                                OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
+                                SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
                             }
                         }
                         else
                         {
-                            OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
-                            SetMOTResult(g_MotCtx, OC_STACK_AUTHENTICATION_FAILURE);
+                            OIC_LOG(ERROR, TAG, "Failed to establish DTLS session.");
+                            SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
                         }
                     }
-                    else
-                    {
-                        OIC_LOG(ERROR, TAG, "Failed to establish DTLS session.");
-                        SetMOTResult(g_MotCtx, OC_STACK_AUTHENTICATION_FAILURE);
-                    }
                 }
             }
         }
+        else
+        {
+            OIC_LOG_V(ERROR, TAG, "Can not find the [%s:%d]'s OTMContext for MOT", endpoint->addr, endpoint->port);
+        }
     }
+
+    OIC_LOG(INFO, TAG, "OUT MOTDtlsHandshakeCB");
 }
 
 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
@@ -975,11 +980,56 @@ static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
     OIC_LOG(INFO, TAG, "IN StartMultipleOwnershipTransfer");
     OCStackResult res = OC_STACK_INVALID_PARAM;
 
+    VERIFY_NON_NULL(TAG, motCtx, ERROR);
     VERIFY_NON_NULL(TAG, selectedDevice, ERROR);
     VERIFY_NON_NULL(TAG, selectedDevice->doxm, ERROR);
-
     motCtx->selectedDeviceInfo = selectedDevice;
 
+    //Checking duplication of Device ID.
+    char* strUuid = NULL;
+    PdmDeviceState_t deviceState = PDM_DEVICE_UNKNOWN;
+    res = PDMGetDeviceState(&selectedDevice->doxm->deviceID, &deviceState);
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+
+    res = ConvertUuidToStr(&selectedDevice->doxm->deviceID, &strUuid);
+    if(OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to convert UUID to str");
+        SetMOTResult(motCtx, res);
+        return res;
+    }
+
+    if(PDM_DEVICE_STALE == deviceState)
+    {
+        OIC_LOG_V(WARNING, TAG, "Detected duplicated UUID in stale status, "
+                           "[%s] will be removed from PDM", strUuid);
+
+        res = PDMDeleteDevice(&selectedDevice->doxm->deviceID);
+        if(OC_STACK_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "Internal error in PDMDeleteDevice");
+            OICFree(strUuid);
+            SetMOTResult(motCtx, res);
+        }
+    }
+    else if(PDM_DEVICE_INIT == deviceState)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s]'s multiple owner transfer process is already started.", strUuid);
+        OICFree(strUuid);
+        SetMOTResult(motCtx, OC_STACK_DUPLICATE_REQUEST);
+        return OC_STACK_OK;
+    }
+
+    res = PDMAddDevice(&selectedDevice->doxm->deviceID);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG_V(INFO, TAG, "Error in PDMAddDevice for [%s]", strUuid);
+        OICFree(strUuid);
+        SetMOTResult(motCtx, res);
+        return res;
+    }
+    OICFree(strUuid);
+
     //Register DTLS event handler to catch the dtls event while handshake
     if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MOTDtlsHandshakeCB))
     {
@@ -989,6 +1039,12 @@ static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
     OicSecOxm_t oxmSel = selectedDevice->doxm->oxmSel;
     OIC_LOG_V(DEBUG, TAG, "Multiple Ownership Transfer method = %d", (int)oxmSel);
 
+    if(OIC_PRECONFIG_PIN != oxmSel && OIC_RANDOM_DEVICE_PIN != oxmSel)
+    {
+        OIC_LOG(ERROR, TAG, "Unsupported OxM");
+        return OC_STACK_ERROR;
+    }
+
     res = OTMSetOTCallback(selectedDevice->doxm->oxmSel, &motCtx->otmCallback);
     if(OC_STACK_OK != res)
     {
@@ -999,12 +1055,6 @@ static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
     VERIFY_NON_NULL(TAG, motCtx->otmCallback.loadSecretCB, ERROR);
     VERIFY_NON_NULL(TAG, motCtx->otmCallback.createSecureSessionCB, ERROR);
 
-    if(OIC_PRECONFIG_PIN != oxmSel && OIC_RANDOM_DEVICE_PIN != oxmSel)
-    {
-        OIC_LOG(ERROR, TAG, "Unsupported OxM");
-        return OC_STACK_ERROR;
-    }
-
     if(OIC_RANDOM_DEVICE_PIN == oxmSel)
     {
         if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
@@ -1013,11 +1063,12 @@ static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
         }
     }
 
-    res = motCtx->otmCallback.loadSecretCB(motCtx);
+    //Save the current context instance to use on the dtls handshake callback
+    res = AddOTMContext(motCtx, selectedDevice->endpoint.addr, selectedDevice->securePort);
     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
 
-    //Save the current context instance to use on the dtls handshake callback
-    g_MotCtx = motCtx;
+    res = motCtx->otmCallback.loadSecretCB(motCtx);
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
 
     res = motCtx->otmCallback.createSecureSessionCB(motCtx);
     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
@@ -1059,32 +1110,9 @@ OCStackResult MOTDoOwnershipTransfer(void* ctx,
 
     //Fill the device UUID for result array.
     size_t devIdx = 0;
-    res = OC_STACK_OK;
     pCurDev = NULL;
     LL_FOREACH(selectedDevicelist, pCurDev)
     {
-        //Checking duplication of Device ID.
-        bool isDuplicate = true;
-        res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
-        VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
-
-        if (isDuplicate)
-        {
-            bool isStale = false;
-            res = PDMIsDeviceStale(&pCurDev->doxm->deviceID, &isStale);
-            VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
-            VERIFY_SUCCESS(TAG, isStale, ERROR);
-
-            if(isStale)
-            {
-                OIC_LOG(INFO, TAG, "Detected duplicated UUID in stale status, "\
-                                   "this UUID will be removed from PDM");
-
-                res = PDMDeleteDevice(&pCurDev->doxm->deviceID);
-                VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
-            }
-        }
-
         memcpy(motCtx->ctxResultArray[devIdx].deviceId.id,
                pCurDev->doxm->deviceID.id,
                UUID_LENGTH);
@@ -1092,6 +1120,7 @@ OCStackResult MOTDoOwnershipTransfer(void* ctx,
         devIdx++;
     }
 
+    motCtx->selectedDeviceInfo = selectedDevicelist;
     res = StartMultipleOwnershipTransfer(motCtx, selectedDevicelist);
     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
 
index cb798da..db70815 100644 (file)
@@ -504,7 +504,7 @@ static OCStackResult RemoveDeviceInfoFromLocal(const OCProvisionDev_t* pTargetDe
      * Change the device status as stale status.
      * If all request are successed, this device information will be deleted.
      */
-    res = PDMSetDeviceStale(&pTargetDev->doxm->deviceID);
+    res = PDMSetDeviceState(&pTargetDev->doxm->deviceID, PDM_DEVICE_STALE);
     if (res != OC_STACK_OK)
     {
         OIC_LOG(WARNING, TAG, "OCRemoveDevice : Failed to set device status as stale");
diff --git a/resource/csdk/security/provisioning/src/otmcontextlist.c b/resource/csdk/security/provisioning/src/otmcontextlist.c
new file mode 100644 (file)
index 0000000..c4b3c40
--- /dev/null
@@ -0,0 +1,114 @@
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "octypes.h"
+#include "ownershiptransfermanager.h"
+#include "utlist.h"
+#include "otmcontextlist.h"
+
+#define TAG "OTM_CTX_LIST"
+
+/**
+ * List for saving the OTMContext to be used while ownership transfer.
+ */
+static OTMContextItem_t* g_otmCtxList = NULL;
+
+void RemoveOTMContext(const char* addr, uint16_t port)
+{
+    OTMContext_t* retCtx = NULL;
+
+    OIC_LOG(DEBUG, TAG, "IN RemoveOTMContext");
+
+    if (NULL != addr && 0 != port)
+    {
+        OTMContextItem_t* item = NULL;
+        OTMContextItem_t* temp = NULL;
+
+        LL_FOREACH_SAFE(g_otmCtxList, item, temp)
+        {
+            if (strncmp(addr, item->endpoint.addr, sizeof(item->endpoint.addr)) == 0 &&
+                port == item->endpoint.port)
+            {
+                OIC_LOG_V(DEBUG, TAG, "Remove [%s:%d]'s context from OTMContext list", addr, port);
+                retCtx = item->otmCtx;
+                item->otmCtx = NULL;
+                LL_DELETE(g_otmCtxList, item);
+                OICFree(item);
+                break;
+            }
+        }
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT RemoveOTMContext");
+
+    return retCtx;
+}
+
+OCStackResult AddOTMContext(OTMContext_t* ctx, const char* addr, uint16_t port)
+{
+    OTMContextItem_t* item = NULL;
+    OTMContextItem_t* temp = NULL;
+    OTMContextItem_t* newItem = NULL;
+
+    OIC_LOG(DEBUG, TAG, "IN AddOTMContext");
+
+    if (NULL == ctx || NULL == addr || 0 == strlen(addr) || 0 == port)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    LL_FOREACH_SAFE(g_otmCtxList, item, temp)
+    {
+            if (strncmp(addr, item->endpoint.addr, sizeof(item->endpoint.addr)) == 0 &&
+                port == item->endpoint.port)
+            {
+                //if OTM Context already exists, just return OC_STACK_OK.
+                OIC_LOG(DEBUG, TAG, "Same OTMContext already exists.");
+                return OC_STACK_OK;
+            }
+    }
+
+    newItem = (OTMContextItem_t*)OICCalloc(1, sizeof(OTMContextItem_t));
+    if (NULL == newItem)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Add [%s:%d]'s context to OTMContext list", addr, port);
+
+    newItem->otmCtx = ctx;
+    OICStrcpy(newItem->endpoint.addr, sizeof(newItem->endpoint.addr), addr);
+    newItem->endpoint.port = port;
+    LL_APPEND(g_otmCtxList, newItem);
+
+    OIC_LOG(DEBUG, TAG, "OUT AddOTMContext");
+
+    return OC_STACK_OK;
+}
+
+const OTMContext_t* GetOTMContext(const char* addr, uint16_t port)
+{
+    OIC_LOG(DEBUG, TAG, "IN GetOTMContext");
+
+    if (NULL != addr && 0 != port)
+    {
+        OTMContextItem_t* item = NULL;
+        OTMContextItem_t* temp = NULL;
+
+        LL_FOREACH_SAFE(g_otmCtxList, item, temp)
+        {
+            if (strncmp(addr, item->endpoint.addr, sizeof(item->endpoint.addr)) == 0 &&
+               port == item->endpoint.port)
+            {
+                OIC_LOG_V(DEBUG, TAG, "Found the OTMContext for [%s:%d]", addr, port);
+                return item->otmCtx;
+            }
+        }
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT GetOTMContext");
+
+    return NULL;
+}
+
index 133f6cb..a1ee60f 100644 (file)
@@ -52,7 +52,6 @@
 #include "cJSON.h"
 #include "global.h"
 #include "utlist.h"
-
 #include "srmresourcestrings.h"
 #include "doxmresource.h"
 #include "pstatresource.h"
@@ -65,6 +64,7 @@
 #include "oxmrandompin.h"
 #include "oxmpreconfpin.h"
 #endif //_ENABLE_MULTIPLE_OWNER_
+#include "otmcontextlist.h"
 #include "pmtypes.h"
 #include "pmutility.h"
 #include "srmutility.h"
@@ -133,7 +133,6 @@ exit:
     return res;
 }
 
-
 /**
  * Function to select appropriate  provisioning method.
  *
@@ -297,58 +296,85 @@ static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
 {
     OIC_LOG_V(DEBUG, TAG, "IN SetResult : %d ", res);
 
-    if(!otmCtx)
+    if(NULL == otmCtx || NULL == otmCtx->selectedDeviceInfo)
     {
         OIC_LOG(WARNING, TAG, "OTMContext is NULL");
         return;
     }
 
-    if(otmCtx->selectedDeviceInfo)
+    //If OTM Context was removed from previous response handler, just exit the current OTM process.
+    if(NULL == GetOTMContext(otmCtx->selectedDeviceInfo->endpoint.addr,
+                             otmCtx->selectedDeviceInfo->securePort))
+    {
+        OIC_LOG(WARNING, TAG, "Current OTM Process has already ended.");
+        return;
+    }
+
+    //Revert psk_info callback and new deivce uuid in case of random PIN OxM
+    if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
     {
-        //Revert psk_info callback and new deivce uuid in case of random PIN OxM
-        if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
+        if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
         {
-            if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
-            {
-                OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
-            }
-            OicUuid_t emptyUuid = { .id={0}};
-            SetUuidForPinBasedOxm(&emptyUuid);
+            OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
         }
+        OicUuid_t emptyUuid = { .id={0}};
+        SetUuidForPinBasedOxm(&emptyUuid);
+    }
 
-        for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
+    for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
+    {
+        if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
+                  otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
         {
-            if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
-                      otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
+            otmCtx->ctxResultArray[i].res = res;
+            if(OC_STACK_OK != res && OC_STACK_CONTINUE != res && OC_STACK_DUPLICATE_REQUEST != res)
             {
-                otmCtx->ctxResultArray[i].res = res;
-                if(OC_STACK_OK != res)
-                {
-                    otmCtx->ctxHasError = true;
-                }
+                otmCtx->ctxHasError = true;
             }
         }
+    }
 
-        g_otmCtx = NULL;
+    //In case of duplicated OTM process, OTMContext and OCDoHandle should not be removed.
+    if(OC_STACK_DUPLICATE_REQUEST != res)
+    {
+        //Remove the current OTM Context from OTM queue
+        RemoveOTMContext(otmCtx->selectedDeviceInfo->endpoint.addr,
+                         otmCtx->selectedDeviceInfo->securePort);
 
-        //If all request is completed, invoke the user callback.
-        if(IsComplete(otmCtx))
-        {
-            otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
-                                       otmCtx->ctxResultArray, otmCtx->ctxHasError);
-            OICFree(otmCtx->ctxResultArray);
-            OICFree(otmCtx);
-        }
-        else
+        //If there is a request being performed, cancel it to prevent retransmission.
+        if(otmCtx->ocDoHandle)
         {
-            if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
-                                                     otmCtx->selectedDeviceInfo->next))
+            OIC_LOG_V(DEBUG, TAG, "OCCancel - %s : %d",
+                    otmCtx->selectedDeviceInfo->endpoint.addr,
+                    otmCtx->selectedDeviceInfo->securePort);
+            if(OC_STACK_OK != OCCancel(otmCtx->ocDoHandle, OC_HIGH_QOS, NULL, 0))
+            {
+                OIC_LOG(WARNING, TAG, "Failed to remove registered callback");
+            }
+            else
             {
-                OIC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
+                otmCtx->ocDoHandle = NULL;
             }
         }
     }
 
+    //If all OTM process is complete, invoke the user callback.
+    if(IsComplete(otmCtx))
+    {
+        otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
+                                   otmCtx->ctxResultArray, otmCtx->ctxHasError);
+        OICFree(otmCtx->ctxResultArray);
+        OICFree(otmCtx);
+    }
+    else
+    {
+        if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
+                                                 otmCtx->selectedDeviceInfo->next))
+        {
+            OIC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
+        }
+    }
+
     OIC_LOG(DEBUG, TAG, "OUT SetResult");
 }
 
@@ -361,86 +387,92 @@ static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
  */
 void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
 {
-    if(NULL != g_otmCtx && NULL != g_otmCtx->selectedDeviceInfo &&
-       NULL != endpoint && NULL != info)
+    if(NULL != endpoint && NULL != info)
     {
         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
                  endpoint->addr, endpoint->port, info->result);
 
-        OicSecDoxm_t* newDevDoxm = g_otmCtx->selectedDeviceInfo->doxm;
-
-        if(NULL != newDevDoxm)
+        OTMContext_t* otmCtx = GetOTMContext(endpoint->addr, endpoint->port);
+        if(otmCtx)
         {
-            OicUuid_t emptyUuid = {.id={0}};
-
-            //Make sure the address matches.
-            if(strncmp(g_otmCtx->selectedDeviceInfo->endpoint.addr,
-               endpoint->addr,
-               sizeof(endpoint->addr)) == 0 &&
-               g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
+            OicSecDoxm_t* newDevDoxm = otmCtx->selectedDeviceInfo->doxm;
+            if(NULL != newDevDoxm)
             {
-                OCStackResult res = OC_STACK_ERROR;
+                OicUuid_t emptyUuid = {.id={0}};
 
-                //If temporal secure sesstion established successfully
-                if(CA_STATUS_OK == info->result &&
-                   false == newDevDoxm->owned &&
-                   memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0)
-                {
-                    //Send request : POST /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
-                    res = PostOwnerUuid(g_otmCtx);
-                    if(OC_STACK_OK != res)
-                    {
-                        OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
-                        SetResult(g_otmCtx, res);
-                    }
-                }
-                //In case of authentication failure
-                else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
+                //Make sure the address matches.
+                if(strncmp(otmCtx->selectedDeviceInfo->endpoint.addr,
+                   endpoint->addr,
+                   sizeof(endpoint->addr)) == 0 &&
+                   otmCtx->selectedDeviceInfo->securePort == endpoint->port)
                 {
-                    //in case of error from owner credential
-                    if(memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0 &&
-                        true == newDevDoxm->owned)
-                    {
-                        OIC_LOG(ERROR, TAG, "The owner credential may incorrect.");
+                    OCStackResult res = OC_STACK_ERROR;
 
-                        if(OC_STACK_OK != RemoveCredential(&(newDevDoxm->deviceID)))
+                    //If temporal secure sesstion established successfully
+                    if(CA_STATUS_OK == info->result &&
+                       false == newDevDoxm->owned &&
+                       memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0)
+                    {
+                        //Send request : POST /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
+                        res = PostOwnerUuid(otmCtx);
+                        if(OC_STACK_OK != res)
                         {
-                            OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
+                            OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
+                            SetResult(otmCtx, res);
                         }
-                        SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
                     }
-                    //in case of error from wrong PIN, re-start the ownership transfer
-                    else if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
+                    //In case of authentication failure
+                    else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
                     {
-                        OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
-
-                        memcpy(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
-                        newDevDoxm->owned = false;
-                        g_otmCtx->attemptCnt++;
+                        //in case of error from owner credential
+                        if(memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0 &&
+                            true == newDevDoxm->owned)
+                        {
+                            OIC_LOG(ERROR, TAG, "The owner credential may incorrect.");
 
-                        if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
+                            if(OC_STACK_OK != RemoveCredential(&(newDevDoxm->deviceID)))
+                            {
+                                OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
+                            }
+                            SetResult(otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
+                        }
+                        //in case of error from wrong PIN, re-start the ownership transfer
+                        else if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
                         {
-                            res = StartOwnershipTransfer(g_otmCtx, g_otmCtx->selectedDeviceInfo);
-                            if(OC_STACK_OK != res)
+                            OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
+
+                            memcpy(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
+                            newDevDoxm->owned = false;
+                            otmCtx->attemptCnt++;
+
+                            if(WRONG_PIN_MAX_ATTEMP > otmCtx->attemptCnt)
+                            {
+                                res = StartOwnershipTransfer(otmCtx, otmCtx->selectedDeviceInfo);
+                                if(OC_STACK_OK != res)
+                                {
+                                    SetResult(otmCtx, res);
+                                    OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
+                                }
+                            }
+                            else
                             {
-                                SetResult(g_otmCtx, res);
-                                OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
+                                OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
+                                SetResult(otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
                             }
                         }
                         else
                         {
-                            OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
-                            SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
+                            OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
+                            SetResult(otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
                         }
                     }
-                    else
-                    {
-                        OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
-                        SetResult(g_otmCtx, OC_STACK_AUTHENTICATION_FAILURE);
-                    }
                 }
             }
         }
+        else
+        {
+            OIC_LOG(ERROR, TAG, "Can not find the OTM Context.");
+        }
     }
 }
 
@@ -583,6 +615,7 @@ static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle U
     VERIFY_NON_NULL(TAG, ctx, WARNING);
 
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    otmCtx->ocDoHandle = NULL;
     (void)UNUSED;
     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
     {
@@ -626,6 +659,7 @@ static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
     VERIFY_NON_NULL(TAG, ctx, WARNING);
 
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    otmCtx->ocDoHandle = NULL;
     (void)UNUSED;
     if  (OC_STACK_OK == clientResponse->result)
     {
@@ -703,6 +737,7 @@ static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNU
     (void)UNUSED;
     OCStackResult res = OC_STACK_OK;
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    otmCtx->ocDoHandle = NULL;
 
     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
     {
@@ -758,6 +793,7 @@ static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle
     VERIFY_NON_NULL(TAG, ctx, WARNING);
 
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    otmCtx->ocDoHandle = NULL;
     (void) UNUSED;
     if  (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
     {
@@ -777,8 +813,15 @@ static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle
             }
         }
 
-        //It will be used in handshake event handler
-        g_otmCtx = otmCtx;
+        //Save the current context instance to use on the dtls handshake callback
+        if(OC_STACK_OK != AddOTMContext(otmCtx,
+                                         otmCtx->selectedDeviceInfo->endpoint.addr,
+                                         otmCtx->selectedDeviceInfo->securePort))
+        {
+            OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to add OTM Context into OTM List.");
+            SetResult(otmCtx, res);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
 
         //Try DTLS handshake to generate secure session
         if(otmCtx->otmCallback.createSecureSessionCB)
@@ -823,6 +866,7 @@ static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNU
     (void)UNUSED;
     OCStackResult res = OC_STACK_OK;
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    otmCtx->ocDoHandle = NULL;
 
     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
     {
@@ -917,6 +961,7 @@ static OCStackApplicationResult OwnerAclHandler(void *ctx, OCDoHandle UNUSED,
     (void)UNUSED;
     OCStackResult res = OC_STACK_OK;
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    otmCtx->ocDoHandle = NULL;
 
     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
     {
@@ -964,6 +1009,7 @@ static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandl
     (void)UNUSED;
     OCStackResult res = OC_STACK_OK;
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    otmCtx->ocDoHandle = NULL;
 
     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
     {
@@ -1011,6 +1057,7 @@ static OCStackApplicationResult ProvisioningStatusHandler(void *ctx, OCDoHandle
     VERIFY_NON_NULL(TAG, ctx, ERROR);
 
     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
+    otmCtx->ocDoHandle = NULL;
     (void)UNUSED;
     OCStackResult res = OC_STACK_OK;
 
@@ -1058,12 +1105,14 @@ static OCStackApplicationResult ReadyForNomalStatusHandler(void *ctx, OCDoHandle
     VERIFY_NON_NULL(TAG, ctx, ERROR);
 
     OTMContext_t* otmCtx = (OTMContext_t*) ctx;
+    otmCtx->ocDoHandle = NULL;
     (void)UNUSED;
 
     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
     {
         OIC_LOG(INFO, TAG, "Device state is in Ready for Normal Operation.");
-        OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
+        OCStackResult res = PDMSetDeviceState(&otmCtx->selectedDeviceInfo->doxm->deviceID,
+                                              PDM_DEVICE_ACTIVE);
          if (OC_STACK_OK == res)
          {
                 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
@@ -1159,7 +1208,7 @@ static OCStackResult PostOwnerCredential(OTMContext_t* otmCtx)
         cbData.cb = &OwnerCredentialHandler;
         cbData.context = (void *)otmCtx;
         cbData.cd = NULL;
-        OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
+        OCStackResult res = OCDoResource(&otmCtx->ocDoHandle, OC_REST_POST, query,
                                          &deviceInfo->endpoint, (OCPayload*)secPayload,
                                          deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
         if (res != OC_STACK_OK)
@@ -1321,7 +1370,7 @@ static OCStackResult PostOwnerAcl(OTMContext_t* otmCtx)
     cbData.cb = &OwnerAclHandler;
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
-    res = OCDoResource(NULL, OC_REST_POST, query,
+    res = OCDoResource(&otmCtx->ocDoHandle, OC_REST_POST, query,
                                      &deviceInfo->endpoint, (OCPayload*)secPayload,
                                      deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     if (res != OC_STACK_OK)
@@ -1383,7 +1432,7 @@ static OCStackResult PostOwnerTransferModeToResource(OTMContext_t* otmCtx)
     cbData.cb = &OwnerTransferModeHandler;
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
-    res = OCDoResource(NULL, OC_REST_POST, query,
+    res = OCDoResource(&otmCtx->ocDoHandle, OC_REST_POST, query,
                        &deviceInfo->endpoint, (OCPayload *)secPayload,
                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     if (res != OC_STACK_OK)
@@ -1422,7 +1471,7 @@ static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
     cbData.cb = &ListMethodsHandler;
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
-    OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
+    OCStackResult res = OCDoResource(&otmCtx->ocDoHandle, OC_REST_GET, query, NULL, NULL,
                                      deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     if (res != OC_STACK_OK)
     {
@@ -1479,7 +1528,7 @@ static OCStackResult PostOwnerUuid(OTMContext_t* otmCtx)
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
 
-    res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload *)secPayload,
+    res = OCDoResource(&otmCtx->ocDoHandle, OC_REST_POST, query, 0, (OCPayload *)secPayload,
             deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     if (res != OC_STACK_OK)
     {
@@ -1538,7 +1587,7 @@ static OCStackResult PostOwnershipInformation(OTMContext_t* otmCtx)
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
 
-    res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
+    res = OCDoResource(&otmCtx->ocDoHandle, OC_REST_POST, query, 0, (OCPayload*)secPayload,
                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     if (res != OC_STACK_OK)
     {
@@ -1591,7 +1640,7 @@ static OCStackResult PostUpdateOperationMode(OTMContext_t* otmCtx)
     cbData.cb = &OperationModeUpdateHandler;
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
-    res = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload *)secPayload,
+    res = OCDoResource(&otmCtx->ocDoHandle, OC_REST_POST, query, 0, (OCPayload *)secPayload,
                        deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     if (res != OC_STACK_OK)
     {
@@ -1614,6 +1663,75 @@ static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selecte
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
     otmCtx->selectedDeviceInfo = selectedDevice;
 
+    //Checking duplication of Device ID.
+    bool isDuplicate = true;
+    res = PDMIsDuplicateDevice(&selectedDevice->doxm->deviceID, &isDuplicate);
+    if (OC_STACK_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "Internal error in PDMIsDuplicateDevice");
+        return res;
+    }
+    if (isDuplicate)
+    {
+        PdmDeviceState_t state = PDM_DEVICE_UNKNOWN;
+        res = PDMGetDeviceState(&selectedDevice->doxm->deviceID, &state);
+        if(OC_STACK_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "Internal error in PDMGetDeviceState");
+            SetResult(otmCtx, res);
+            return res;
+        }
+
+        char* strUuid = NULL;
+        res = ConvertUuidToStr(&selectedDevice->doxm->deviceID, &strUuid);
+        if(OC_STACK_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "Failed to convert UUID to str");
+            SetResult(otmCtx, res);
+            return res;
+        }
+
+        if(PDM_DEVICE_STALE == state)
+        {
+            OIC_LOG(INFO, TAG, "Detected duplicated UUID in stale status, "
+                               "this UUID will be removed from PDM");
+
+            res = PDMDeleteDevice(&selectedDevice->doxm->deviceID);
+            if(OC_STACK_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "Internal error in PDMDeleteDevice");
+                OICFree(strUuid);
+                SetResult(otmCtx, res);
+                return res;
+            }
+        }
+        else if(PDM_DEVICE_INIT == state)
+        {
+            OIC_LOG_V(ERROR, TAG, "[%s]'s ownership transfer process is already started.", strUuid);
+            OICFree(strUuid);
+            SetResult(otmCtx, OC_STACK_DUPLICATE_REQUEST);
+            return OC_STACK_OK;
+        }
+        else
+        {
+            OIC_LOG(ERROR, TAG, "Unknow device status while OTM.");
+            OICFree(strUuid);
+            SetResult(otmCtx, OC_STACK_ERROR);
+            return OC_STACK_ERROR;
+        }
+    }
+    else
+    {
+        res = PDMAddDevice(&selectedDevice->doxm->deviceID);
+        if(OC_STACK_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "Internal error in PDMAddDevice");
+            SetResult(otmCtx, res);
+            return res;
+        }
+    }
+
+
     //Set to the lowest level OxM, and then find more higher level OxM.
     res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
                                    selectedDevice->doxm->oxmLen,
@@ -1728,41 +1846,6 @@ OCStackResult OTMDoOwnershipTransfer(void* ctx,
     //Fill the device UUID for result array.
     for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
     {
-        //Checking duplication of Device ID.
-        bool isDuplicate = true;
-        res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
-        if (OC_STACK_OK != res)
-        {
-            goto error;
-        }
-        if (isDuplicate)
-        {
-            bool isStale = false;
-            res = PDMIsDeviceStale(&pCurDev->doxm->deviceID, &isStale);
-            if(OC_STACK_OK != res)
-            {
-                OIC_LOG(ERROR, TAG, "Internal error in PDMIsDeviceStale");
-                goto error;
-            }
-            if(isStale)
-            {
-                OIC_LOG(INFO, TAG, "Detected duplicated UUID in stale status, "\
-                                   "this UUID will be removed from PDM");
-
-                res = PDMDeleteDevice(&pCurDev->doxm->deviceID);
-                if(OC_STACK_OK != res)
-                {
-                    OIC_LOG(ERROR, TAG, "Internal error in PDMDeleteDevice");
-                    goto error;
-                }
-            }
-            else
-            {
-                OIC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device UUID is duplicated");
-                res = OC_STACK_INVALID_PARAM;
-                goto error;
-            }
-        }
         memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
                pCurDev->doxm->deviceID.id,
                UUID_LENGTH);
@@ -1826,7 +1909,7 @@ OCStackResult PostProvisioningStatus(OTMContext_t* otmCtx)
     cbData.cb = &ProvisioningStatusHandler;
     cbData.context = (void*)otmCtx;
     cbData.cd = NULL;
-    OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
+    OCStackResult ret = OCDoResource(&otmCtx->ocDoHandle, OC_REST_POST, query, 0, (OCPayload*)secPayload,
             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
     if (ret != OC_STACK_OK)
@@ -1884,7 +1967,7 @@ OCStackResult PostNormalOperationStatus(OTMContext_t* otmCtx)
     cbData.cb = &ReadyForNomalStatusHandler;
     cbData.context = (void*)otmCtx;
     cbData.cd = NULL;
-    OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query, 0, (OCPayload*)secPayload,
+    OCStackResult ret = OCDoResource(&otmCtx->ocDoHandle, OC_REST_POST, query, 0, (OCPayload*)secPayload,
             otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
     OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
     if (ret != OC_STACK_OK)
index b0cf0f1..68c8ece 100644 (file)
@@ -36,9 +36,6 @@
 
 #define TAG "OIC_PDM"
 
-#define PDM_STALE_STATE 1
-#define PDM_ACTIVE_STATE 0
-
 #define PDM_FIRST_INDEX 0
 #define PDM_SECOND_INDEX 1
 
@@ -203,7 +200,7 @@ OCStackResult PDMAddDevice(const OicUuid_t *UUID)
     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, UUID, UUID_LENGTH, SQLITE_STATIC);
     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
 
-    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_ACTIVE_STATE);
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_DEVICE_INIT);
     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
 
     res = sqlite3_step(stmt);
@@ -225,42 +222,6 @@ OCStackResult PDMAddDevice(const OicUuid_t *UUID)
 }
 
 /**
- * Function to check whether device is stale or not
- */
-OCStackResult PDMIsDeviceStale(const OicUuid_t *uuid, bool *result)
-{
-    if (NULL == uuid || NULL == result)
-    {
-        OIC_LOG(ERROR, TAG, "UUID or result is NULL");
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    sqlite3_stmt *stmt = 0;
-    int res = 0;
-    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_DEVICE_STATUS, strlen(PDM_SQLITE_GET_DEVICE_STATUS) + 1,
-                              &stmt, NULL);
-    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
-
-    res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, uuid, UUID_LENGTH, SQLITE_STATIC);
-    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
-
-    bool retValue = false;
-    while(SQLITE_ROW == sqlite3_step(stmt))
-    {
-        int tempStaleStateFromDb = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
-        OIC_LOG_V(DEBUG, TAG, "Stale state is %d", tempStaleStateFromDb);
-        if (PDM_STALE_STATE == tempStaleStateFromDb)
-        {
-            OIC_LOG(INFO, TAG, "Device is stale");
-            retValue = true;
-        }
-    }
-    *result = retValue;
-    sqlite3_finalize(stmt);
-    return OC_STACK_OK;
-}
-
-/**
  *function to get Id for given UUID
  */
 static OCStackResult getIdForUUID(const OicUuid_t *UUID , int *id)
@@ -336,7 +297,7 @@ static OCStackResult addlink(int id1, int id2)
     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
 
-    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_ACTIVE_STATE);
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_DEVICE_ACTIVE);
     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
 
     if (sqlite3_step(stmt) != SQLITE_DONE)
@@ -358,26 +319,27 @@ OCStackResult PDMLinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
         return  OC_STACK_INVALID_PARAM;
     }
 
-    bool result = false;
-    if (OC_STACK_OK != PDMIsDeviceStale(UUID1, &result))
+    PdmDeviceState_t state = PDM_DEVICE_UNKNOWN;
+    if (OC_STACK_OK != PDMGetDeviceState(UUID1, &state))
     {
         OIC_LOG(ERROR, TAG, "Internal error occured");
         return OC_STACK_ERROR;
     }
-    if (result)
+    if (PDM_DEVICE_ACTIVE != state)
     {
-        OIC_LOG(ERROR, TAG, "UUID1:Stale device");
+        OIC_LOG_V(ERROR, TAG, "UUID1: Device state is not active : %d", state);
         return OC_STACK_INVALID_PARAM;
     }
-    result = false;
-    if (OC_STACK_OK != PDMIsDeviceStale(UUID2, &result))
+
+    state = PDM_DEVICE_UNKNOWN;
+    if (OC_STACK_OK != PDMGetDeviceState(UUID2, &state))
     {
         OIC_LOG(ERROR, TAG, "Internal error occured");
         return OC_STACK_ERROR;
     }
-    if (result)
+    if (PDM_DEVICE_ACTIVE != state)
     {
-        OIC_LOG(ERROR, TAG, "UUID2:Stale device");
+        OIC_LOG_V(ERROR, TAG, "UUID2: Device state is not active : %d", state);
         return OC_STACK_INVALID_PARAM;
     }
 
@@ -546,8 +508,7 @@ OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* u
         return OC_STACK_INVALID_PARAM;
     }
     ASCENDING_ORDER(id1, id2);
-    return updateLinkState(id1, id2, PDM_STALE_STATE);
-
+    return updateLinkState(id1, id2, PDM_DEVICE_STALE);
 }
 
 OCStackResult PDMGetOwnedDevices(OCUuidList_t **uuidList, size_t *numOfDevices)
@@ -602,7 +563,7 @@ static OCStackResult getUUIDforId(int id, OicUuid_t *uid, bool *result)
         memcpy(uid, ptr, sizeof(OicUuid_t));
 
         int temp = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
-        if(PDM_STALE_STATE == temp)
+        if(PDM_DEVICE_STALE == temp)
         {
             if(result)
             {
@@ -635,16 +596,16 @@ OCStackResult PDMGetLinkedDevices(const OicUuid_t *UUID, OCUuidList_t **UUIDLIST
         OIC_LOG(ERROR, TAG, "Not null list will cause memory leak");
         return OC_STACK_INVALID_PARAM;
     }
-    bool result = false;
-    OCStackResult ret = PDMIsDeviceStale(UUID, &result);
+    PdmDeviceState_t state = PDM_DEVICE_UNKNOWN;
+    OCStackResult ret = PDMGetDeviceState(UUID, &state);
     if (OC_STACK_OK != ret)
     {
         OIC_LOG(ERROR, TAG, "Internal error occured");
         return OC_STACK_ERROR;
     }
-    if (result)
+    if (PDM_DEVICE_ACTIVE != state)
     {
-        OIC_LOG(ERROR, TAG, "Device is stale");
+        OIC_LOG_V(ERROR, TAG, "Device state is not active : %d", state);
         return OC_STACK_INVALID_PARAM;
     }
     int id = 0;
@@ -714,7 +675,7 @@ OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t **staleDevList, size_t *num
                               strlen(PDM_SQLITE_GET_STALE_INFO) + 1, &stmt, NULL);
     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
 
-    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, PDM_STALE_STATE);
+    res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, PDM_DEVICE_STALE);
     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
 
     size_t counter  = 0;
@@ -801,27 +762,27 @@ OCStackResult PDMIsLinkExists(const OicUuid_t* uuidOfDevice1, const OicUuid_t* u
         return OC_STACK_INVALID_PARAM;
     }
 
-    bool isStale = false;
-    if (OC_STACK_OK != PDMIsDeviceStale(uuidOfDevice1, &isStale))
+    PdmDeviceState_t state = PDM_DEVICE_UNKNOWN;
+    if (OC_STACK_OK != PDMGetDeviceState(uuidOfDevice1, &state))
     {
         OIC_LOG(ERROR, TAG, "uuidOfDevice1:Internal error occured");
         return OC_STACK_ERROR;
     }
-    if (isStale)
+    if (PDM_DEVICE_ACTIVE != state)
     {
-        OIC_LOG(ERROR, TAG, "uuidOfDevice1:Device is stale");
+        OIC_LOG_V(ERROR, TAG, "uuidOfDevice1:Device state is not active : %d", state);
         return OC_STACK_INVALID_PARAM;
     }
 
-    isStale = false;
-    if (OC_STACK_OK != PDMIsDeviceStale(uuidOfDevice2, &isStale))
+    state = PDM_DEVICE_UNKNOWN;
+    if (OC_STACK_OK != PDMGetDeviceState(uuidOfDevice2, &state))
     {
         OIC_LOG(ERROR, TAG, "uuidOfDevice2:Internal error occured");
         return OC_STACK_ERROR;
     }
-    if (isStale)
+    if (PDM_DEVICE_ACTIVE != state)
     {
-        OIC_LOG(ERROR, TAG, "uuidOfDevice2:Device is stale");
+        OIC_LOG_V(ERROR, TAG, "uuidOfDevice2:Device state is not active : %d", state);
         return OC_STACK_INVALID_PARAM;
     }
 
@@ -850,7 +811,7 @@ OCStackResult PDMIsLinkExists(const OicUuid_t* uuidOfDevice1, const OicUuid_t* u
     return OC_STACK_OK;
 }
 
-static OCStackResult updateDeviceState(const OicUuid_t *uuid, int state)
+static OCStackResult updateDeviceState(const OicUuid_t *uuid, PdmDeviceState_t state)
 {
     sqlite3_stmt *stmt = 0;
     int res = 0 ;
@@ -907,23 +868,30 @@ static OCStackResult updateLinkForStaleDevice(const OicUuid_t *devUuid)
     return OC_STACK_OK;
 }
 
-OCStackResult PDMSetDeviceStale(const OicUuid_t* uuidOfDevice)
+OCStackResult PDMSetDeviceState(const OicUuid_t* uuid, PdmDeviceState_t state)
 {
+    OCStackResult res = OC_STACK_ERROR;
+
     CHECK_PDM_INIT(TAG);
-    if (NULL == uuidOfDevice)
+    if (NULL == uuid)
     {
         OIC_LOG(ERROR, TAG, "Invalid PARAM");
         return  OC_STACK_INVALID_PARAM;
     }
     begin();
-    OCStackResult res = updateLinkForStaleDevice(uuidOfDevice);
-    if (OC_STACK_OK != res)
+
+    if(PDM_DEVICE_STALE == state)
     {
-        rollback();
-        OIC_LOG(ERROR, TAG, "unable to update links");
-        return res;
+        res = updateLinkForStaleDevice(uuid);
+        if (OC_STACK_OK != res)
+        {
+            rollback();
+            OIC_LOG(ERROR, TAG, "unable to update links");
+            return res;
+        }
     }
-    res = updateDeviceState(uuidOfDevice, PDM_STALE_STATE);
+
+    res = updateDeviceState(uuid, state);
     if (OC_STACK_OK != res)
     {
         rollback();
@@ -933,3 +901,32 @@ OCStackResult PDMSetDeviceStale(const OicUuid_t* uuidOfDevice)
     commit();
     return OC_STACK_OK;
 }
+
+OCStackResult PDMGetDeviceState(const OicUuid_t *uuid, PdmDeviceState_t* result)
+{
+    if (NULL == uuid || NULL == result)
+    {
+        OIC_LOG(ERROR, TAG, "UUID or result is NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    sqlite3_stmt *stmt = 0;
+    int res = 0;
+    res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_DEVICE_STATUS, strlen(PDM_SQLITE_GET_DEVICE_STATUS) + 1,
+                              &stmt, NULL);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, uuid, UUID_LENGTH, SQLITE_STATIC);
+    PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+    *result = PDM_DEVICE_UNKNOWN;
+    while(SQLITE_ROW == sqlite3_step(stmt))
+    {
+        int tempStaleStateFromDb = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
+        OIC_LOG_V(DEBUG, TAG, "Device state is %d", tempStaleStateFromDb);
+        *result = (PdmDeviceState_t)tempStaleStateFromDb;
+    }
+    sqlite3_finalize(stmt);
+    return OC_STACK_OK;
+}
+
index 3751f2b..5bbf811 100644 (file)
@@ -75,10 +75,12 @@ TEST(PDMIsDuplicateDeviceTest, ValidUUID)
 {
     OicUuid_t uid1 = {{0,}};
     memcpy(&uid1.id, ID_1, sizeof(uid1.id));
-    PDMAddDevice(&uid1);
+    EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid1));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid1, PDM_DEVICE_ACTIVE));
     OicUuid_t uid2 = {{0,}};
     memcpy(&uid2.id, ID_2, sizeof(uid2.id));
-    PDMAddDevice(&uid2);
+    EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid2));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid2, PDM_DEVICE_ACTIVE));
     OicUuid_t uid3 = {{0,}};
     memcpy(&uid3.id, ID_3, sizeof(uid3.id));
     bool isDuplicate = true;
@@ -125,10 +127,14 @@ TEST(PDMLinkDevicesTest, ValidCase)
 {
     OicUuid_t uid1 = {{0,}};
     memcpy(&uid1.id, ID_4, sizeof(uid1.id));
-    PDMAddDevice(&uid1);
+    EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid1));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid1, PDM_DEVICE_ACTIVE));
+
     OicUuid_t uid2 = {{0,}};
     memcpy(&uid2.id, ID_5, sizeof(uid2.id));
-    PDMAddDevice(&uid2);
+    EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid2));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid2, PDM_DEVICE_ACTIVE));
+
     EXPECT_EQ(OC_STACK_OK, PDMLinkDevices(&uid1, &uid2));
 }
 
@@ -234,6 +240,8 @@ TEST(PDMSetLinkStale, ValidCase)
 
     EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid1));
 
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid1, PDM_DEVICE_ACTIVE));
+
     EXPECT_EQ(OC_STACK_OK, PDMLinkDevices(&uid1, &uid2));
 
     EXPECT_EQ(OC_STACK_OK, PDMSetLinkStale(&uid1, &uid2));
@@ -267,9 +275,12 @@ TEST(PDMIsLinkExistsTest, DuplicateID)
     OicUuid_t uid1 = {{0,}};
     memcpy(&uid1.id, ID_7, sizeof(uid1.id));
     EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid1));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid1, PDM_DEVICE_ACTIVE));
+
     OicUuid_t uid2 = {{0,}};
     memcpy(&uid2.id, ID_8, sizeof(uid2.id));
     EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid2));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid2, PDM_DEVICE_ACTIVE));
 
     bool linkExisits = true;
     OCStackResult res = PDMIsLinkExists(&uid1, &uid2, &linkExisits);
@@ -280,7 +291,7 @@ TEST(PDMIsLinkExistsTest, DuplicateID)
 TEST(PDMSetDeviceStaleTest, NULLUUID)
 {
     EXPECT_EQ(OC_STACK_OK, PDMInit(NULL));
-    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMSetDeviceStale(NULL));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMSetDeviceState(NULL, PDM_DEVICE_STALE));
 }
 
 TEST(PDMSetDeviceStaleTest, VALIDUUID)
@@ -289,7 +300,7 @@ TEST(PDMSetDeviceStaleTest, VALIDUUID)
     OicUuid_t uid1 = {{0,}};
     memcpy(&uid1.id, ID_9, sizeof(uid1.id));
     EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid1));
-    EXPECT_EQ(OC_STACK_OK,PDMSetDeviceStale(&uid1));
+    EXPECT_EQ(OC_STACK_OK,PDMSetDeviceState(&uid1, PDM_DEVICE_STALE));
 }
 
 TEST(PDMSetDeviceStaleTest, StaleDeviceNotinDeviceList)
@@ -298,7 +309,7 @@ TEST(PDMSetDeviceStaleTest, StaleDeviceNotinDeviceList)
     OicUuid_t uid1 = {{0,}};
     memcpy(&uid1.id, ID_10, sizeof(uid1.id));
     EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid1));
-    EXPECT_EQ(OC_STACK_OK,PDMSetDeviceStale(&uid1));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid1, PDM_DEVICE_STALE));
 
     OCUuidList_t *list = NULL;
     size_t noOfDevcies = 0;
@@ -324,14 +335,17 @@ TEST(PDMSetDeviceStaleTest, StaleDeviceNotinLinkedDevice)
     memcpy(&uid3.id, ID_13, sizeof(uid3.id));
 
     EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid1));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid1, PDM_DEVICE_ACTIVE));
     EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid2));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid2, PDM_DEVICE_ACTIVE));
     EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid3));
+    EXPECT_EQ(OC_STACK_OK, PDMSetDeviceState(&uid3, PDM_DEVICE_ACTIVE));
 
     EXPECT_EQ(OC_STACK_OK, PDMLinkDevices(&uid1, &uid2));
     EXPECT_EQ(OC_STACK_OK, PDMLinkDevices(&uid2, &uid3));
     EXPECT_EQ(OC_STACK_OK, PDMLinkDevices(&uid1, &uid3));
 
-    EXPECT_EQ(OC_STACK_OK,PDMSetDeviceStale(&uid1));
+    EXPECT_EQ(OC_STACK_OK,PDMSetDeviceState(&uid1, PDM_DEVICE_STALE));
 
     OCUuidList_t *list1 = NULL;
     size_t noOfDevices1 = 0;
index 30a7ba5..a94f750 100644 (file)
@@ -132,6 +132,10 @@ static void FreeACE(OicSecAce_t *ace)
         validity = NULL;
     }
 
+#ifdef _ENABLE_MULTIPLE_OWNER_
+    OICFree(ace->eownerID);
+#endif
+
     //Clean ACE
     OICFree(ace);
     ace = NULL;
@@ -252,6 +256,18 @@ OicSecAce_t* DuplicateACE(const OicSecAce_t* ace)
             }
         }
 
+#ifdef _ENABLE_MULTIPLE_OWNER_
+        if (ace->eownerID)
+        {
+            if (NULL == newAce->eownerID)
+            {
+                newAce->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
+                VERIFY_NON_NULL(TAG, (newAce->eownerID), ERROR);
+            }
+            memcpy(newAce->eownerID->id, ace->eownerID->id, sizeof(ace->eownerID->id));
+        }
+#endif
+
         newAce->next = NULL;
     }
 
@@ -1686,6 +1702,21 @@ static bool IsSameValidities(OicSecValidity_t* validities1, OicSecValidity_t* va
     return false;
 }
 
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static bool IsSameEowner(OicUuid_t* eowner1, OicUuid_t* eowner2)
+{
+    if(NULL != eowner1 && NULL != eowner2)
+    {
+        if (memcmp(eowner1->id, eowner2->id, sizeof(eowner1->id)) == 0)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+#endif
+
 static bool IsSameACE(OicSecAce_t* ace1, OicSecAce_t* ace2)
 {
     if(ace1 && ace2)
@@ -1710,6 +1741,13 @@ static bool IsSameACE(OicSecAce_t* ace1, OicSecAce_t* ace2)
             return false;
         }
 
+#ifdef _ENABLE_MULTIPLE_OWNER_
+        if(false == IsSameEowner(ace1->eownerID, ace2->eownerID))
+        {
+            return false;
+        }
+#endif
+
         return true;
     }
 
index e75a965..9fb2844 100644 (file)
@@ -930,15 +930,30 @@ void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
         const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
         if(authenticatedSubOwnerInfo)
         {
-            OicSecSubOwner_t* subOwnerInst = (OicSecSubOwner_t*)OICMalloc(sizeof(OicSecSubOwner_t));
-            if(subOwnerInst)
+            OicSecSubOwner_t* subOwnerInst = NULL;
+            LL_FOREACH(gDoxm->subOwners, subOwnerInst)
             {
-                OIC_LOG(DEBUG, TAG, "Adding New SubOwner");
-                memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id, authenticatedSubOwnerInfo->identity.id_length);
-                LL_APPEND(gDoxm->subOwners, subOwnerInst);
-                if(!UpdatePersistentStorage(gDoxm))
+                if(0 == memcmp(subOwnerInst->uuid.id,
+                               authenticatedSubOwnerInfo->identity.id,
+                               authenticatedSubOwnerInfo->identity.id_length))
                 {
-                    OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
+                    break;
+                }
+            }
+
+            if(NULL == subOwnerInst)
+            {
+                subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
+                if(subOwnerInst)
+                {
+                    OIC_LOG(DEBUG, TAG, "Adding New SubOwner");
+                    memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id,
+                           authenticatedSubOwnerInfo->identity.id_length);
+                    LL_APPEND(gDoxm->subOwners, subOwnerInst);
+                    if(!UpdatePersistentStorage(gDoxm))
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
+                    }
                 }
             }
         }