OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
    {
        if(!resultCallback)
        {
            oclog() <<"Result callback can't be null";
            return OC_STACK_INVALID_PARAM;
        }

        OCStackResult result;
        auto cLock = m_csdkLock.lock();

        if(cLock)
        {
            ProvisionContext* context = new ProvisionContext(resultCallback);

            std::lock_guard<std::recursive_mutex> lock(*cLock);
            result = OCDoOwnershipTransfer(static_cast<void*>(context),
                    devPtr, &OCSecureResource::callbackWrapper);
        }
        else
        {
            oclog() <<"Mutex not found";
            result = OC_STACK_ERROR;
        }
        return result;
    }
static int registerDevices(void)
{
    // check |unown_list| for registering devices
    if(!g_unown_list || 0>=g_unown_cnt)
    {
        printf("   > Unowned Device List, to Register Devices, is Empty\n");
        printf("   > Please Discover Unowned Devices first, with [10|11] Menu\n");
        return 0;  // normal case
    }

    // call |OCDoOwnershipTransfer| API actually
    // calling this API with callback actually acts like blocking
    // for error checking, the return value saved and printed
    g_doneCB = false;
    printf("   Registering All Discovered Unowned Devices..\n");
    OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
    if(OC_STACK_OK != rst)
    {
        OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
        return -1;
    }
    if(waitCallbackRet())  // input |g_doneCB| flag implicitly
    {
        OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
        return -1;
    }

    // display the registered result
    printf("   > Registered Discovered Unowned Devices\n");
    printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");

    return 0;
}
/**
 * Provisioning client sample using ProvisioningAPI
 */
int main()
{
    OCStackResult res = OC_STACK_OK;
    int unused;
    (void)unused;

    // Initialize Persistent Storage for SVR database
    OCPersistentStorage ps = { .open = NULL,
                               .read = NULL,
                               .write = NULL,
                               .close = NULL,
                               .unlink = NULL };
    ps.open = client_fopen;
    ps.read = fread;
    ps.write = fwrite;
    ps.close = fclose;
    ps.unlink = unlink;
    OCRegisterPersistentStorageHandler(&ps);

    if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
    {
        OC_LOG(ERROR, TAG, "OCStack init error");
        goto error;
    }

    OCProvisionDev_t* pDeviceList = NULL;
    res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
    if(OC_STACK_OK != res)
    {
        OC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
        goto error;
    }

    OCProvisionDev_t* pCurDev = pDeviceList;
    int i;
    while(pCurDev !=NULL)
    {
        for(i = 0; i < UUID_LENGTH; i++)
            printf("%c", pCurDev->doxm->deviceID.id[i]);
        printf("\n");
        pCurDev = pCurDev->next;
    }

    //Register callback function to each OxM
    OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
                                         .createSecureSessionCB=NULL,
                                         .createSelectOxmPayloadCB=NULL,
                                         .createOwnerTransferPayloadCB=NULL};
    justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
    justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
    justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
    justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
    OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);

    OTMCallbackData_t pinBasedCBData = {.loadSecretCB=NULL,
                                         .createSecureSessionCB=NULL,
                                         .createSelectOxmPayloadCB=NULL,
                                         .createOwnerTransferPayloadCB=NULL};
    pinBasedCBData.loadSecretCB = InputPinCodeCallback;
    pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
    pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
    pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
    OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);

    SetInputPinCB(&InputPinCB);

    char* myContext = "OTM Context";
    //Perform ownership transfer
    res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
    if(OC_STACK_OK == res)
    {
        OC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
    }
    else
    {
        OC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
    }

    gOwnershipState = 0;
    while ( gOwnershipState == 0 )
    {
        if (OCProcess() != OC_STACK_OK)
        {
            OC_LOG(ERROR, TAG, "OCStack process error");
            goto error;
        }
        sleep(1);
    }

// Credential & ACL provisioning between two devices.

    OCProvisionDev_t *pOwnedList = NULL;
    OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
    int nOwnedDevice = 0;

    res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
    if (OC_STACK_OK == res)
    {
        printf("################## Owned Device List #######################\n");
        while (pOwnedList != NULL)
        {
            nOwnedDevice ++;
            printf(" %d : ", nOwnedDevice);
            for (int i = 0; i < UUID_LENGTH; i++)
            {
                printf("%c", pOwnedList->doxm->deviceID.id[i]);
            }
            printf("\n");
            pOwnedDevices[nOwnedDevice] = pOwnedList;
            pOwnedList = pOwnedList->next;
        }
    }
    else
    {
        OC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
    }

    int Device1 = 0;
    int Device2 = 0;

    printf("Select 2 devices for Credential & ACL provisioning\n");
    printf("Device 1: ");
    unused = scanf("%d", &Device1);
    printf("Device 2: ");
    unused = scanf("%d", &Device2);


    gAcl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
    if (NULL == gAcl1)
    {
        OC_LOG(ERROR, TAG, "Error while memory allocation");
        goto error;
    }

    gAcl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
    if (NULL == gAcl2)
    {
        OC_LOG(ERROR, TAG, "Error while memory allocation");
        goto error;
    }

    printf("Input ACL for Device1\n");
    if ( 0 == InputACL(gAcl1))
    {
        printf("Success Input ACL\n");
    }
    else
    {
        OC_LOG(ERROR, TAG, "InputACL error");
        goto error;
    }

    printf("Input ACL for Device2\n");
    if (0 == InputACL(gAcl2))
    {
        printf("Success Input ACL\n");
    }
    else
    {
        OC_LOG(ERROR, TAG, "InputACL error");
        goto error;
    }
    char *ctx = "DUMMY";
    OCProvisionPairwiseDevices(ctx,SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128, pOwnedDevices[Device1],
                           gAcl1, pOwnedDevices[Device2], gAcl2, ProvisionPairwiseCB);

    gOwnershipState = 0;
    while ( gOwnershipState == 0 )
    {
        if (OCProcess() != OC_STACK_OK)
        {
            OC_LOG(ERROR, TAG, "OCStack process error");
            goto error;
        }
        sleep(1);
    }

    if (OCStop() != OC_STACK_OK)
    {
        OC_LOG(ERROR, TAG, "OCStack process error");
        goto error;
    }

error:
    deleteACL(gAcl1);
    deleteACL(gAcl2);
    OCDeleteDiscoveredDevices(&pDeviceList);
    OCDeleteDiscoveredDevices(&pOwnedList);

    return 0;
}