Implement d2d-subowner
authorsaerome.kim <saerome.kim@samsung.com>
Tue, 19 Dec 2017 04:53:16 +0000 (13:53 +0900)
committersaerome.kim <saerome.kim@samsung.com>
Mon, 2 Jul 2018 10:38:38 +0000 (19:38 +0900)
- Discover MOT enabled devices
- Multiple Onwership Transfer

Signed-off-by: saerome.kim <saerome.kim@samsung.com>
install.sh [new file with mode: 0755]
src/d2d-subowner/d2ds-log.h
src/d2d-subowner/d2ds-service-interface.c
src/d2d-subowner/d2ds-subowner.c
src/d2d-subowner/d2ds-subowner.h [new file with mode: 0644]
src/d2d-subowner/d2ds.c
src/d2d-subowner/d2ds.h
test/subownerclient.c

diff --git a/install.sh b/install.sh
new file mode 100755 (executable)
index 0000000..139c4fb
--- /dev/null
@@ -0,0 +1,9 @@
+sdb root on
+sdb push ~/GBS-ROOT/50std/local/repos/tizen50std/armv7l/RPMS/d2d-manager-0.0.1-0.armv7l.rpm /tmp/
+sdb push ~/GBS-ROOT/50std/local/repos/tizen50std/armv7l/RPMS/d2d-manager-devel-0.0.1-0.armv7l.rpm /tmp/
+sdb shell mount -o remount,rw /
+sdb shell rpm -Uvh --force /tmp/d2d-manager-0.0.1-0.armv7l.rpm
+sdb shell rpm -Uvh --force /tmp/d2d-manager-devel-0.0.1-0.armv7l.rpm
+sync
+sdb dlog -c
+sdb dlog -v time D2D_SUBOWNER OIC_PM_UTILITY OIC_RI_STACK OIC_CA_CONN_MGR OIC_CA_PRTCL_MSG OIC_RI_CLIENTCB OIC_RM_UTIL OIC_RM_RAP
index 036be412b90daeceec469c6a0419a46252d4a55b..82aadd746d22a52c5b03c339b5ccdbf758d8ecf5 100644 (file)
 #ifndef __D2DS_LOG_H__\r
 #define __D2DS_LOG_H__\r
 \r
-#ifdef D2DS_LOG_TAG\r
-#undef D2DS_LOG_TAG\r
+#ifdef LOG_TAG\r
+#undef LOG_TAG\r
 #endif\r
 \r
 #ifdef USE_DLOG\r
 #include <dlog.h>\r
 \r
-#undef D2DS_LOG_TAG\r
-#define D2DS_LOG_TAG "D2D_SUBOWNER"\r
+#undef LOG_TAG\r
+#define LOG_TAG "D2D_SUBOWNER"\r
 \r
 #define D2DS_LOGV(format, args...) LOGV(format, ##args)\r
 #define D2DS_LOGD(format, args...) LOGD(format, ##args)\r
index 52473afb8790037f3c4a6e9a0303e1f4d231df08..f32aa4a58ac6a84ef718af8a4b90167513bc890c 100644 (file)
@@ -22,6 +22,7 @@
 #include "d2ds-log.h"\r
 #include "d2ds-util.h"\r
 #include "d2ds-service.h"\r
+#include "d2ds-subowner.h"\r
 #include "d2ds-service-interface.h"\r
 #include "d2ds-generated-code.h"\r
 \r
@@ -139,11 +140,10 @@ static gboolean _d2ds_dbus_handle_disc_mot_enb_devs(NetD2ds *object,
 \r
        d2ds_check_null_ret_error("service", service, FALSE);\r
 \r
-#if 0\r
        ret = d2ds_request_disc_mot_enb_devs(service);\r
        if (D2DS_ERROR_NONE != ret)\r
                D2DS_LOGE("Failed to d2ds_request_disc_mot_enb_devs !");\r
-#endif\r
+\r
        net_d2ds_complete_disc_mot_enb_devs(object, invocation, ret);\r
 \r
        return TRUE;\r
@@ -158,11 +158,11 @@ static gboolean _d2ds_dbus_handle_disc_moted_devs(NetD2ds *object,
 \r
        d2ds_check_null_ret_error("service", service, FALSE);\r
 \r
-#if 0\r
-       ret = d2ds_request_disc_moted_devs(service);\r
+\r
+       ret = d2ds_request_disc_owned_devs(service);\r
        if (D2DS_ERROR_NONE != ret)\r
-               D2DS_LOGE("Failed to d2ds_request_disc_moted_devs !");\r
-#endif\r
+               D2DS_LOGE("Failed to d2ds_request_disc_owned_devs !");\r
+\r
        net_d2ds_complete_disc_moted_devs(object, invocation, ret);\r
 \r
        return TRUE;\r
@@ -179,11 +179,11 @@ static gboolean _d2ds_dbus_handle_mot(NetD2ds *object,
 \r
        d2ds_check_null_ret_error("service", service, FALSE);\r
 \r
-#if 0\r
-       ret = d2ds_request_mot(service);\r
+\r
+       ret = d2ds_request_mot(service, target, pin);\r
        if (D2DS_ERROR_NONE != ret)\r
                D2DS_LOGE("Failed to d2ds_request_disc_moted_devs !");\r
-#endif\r
+\r
        net_d2ds_complete_mot(object, invocation, ret);\r
 \r
        return TRUE;\r
@@ -283,6 +283,13 @@ static gboolean _d2ds_dbus_handle_enable(Enabler *object,
        enabler_complete_enable(object, invocation, ret);\r
        service->d2ds_activated = TRUE;\r
 \r
+       /* Intialize subowner client */\r
+       ret = d2ds_request_enable(service);\r
+       if (D2DS_ERROR_NONE != ret) {\r
+               D2DS_LOGE("d2ds_request_enable() Fail(%d)", ret);\r
+               return FALSE;\r
+       }\r
+\r
        /* Notify d2ds enabled */\r
        net_d2ds_emit_subowner_enabled(d2ds_dbus_get_object(), ret);\r
 \r
@@ -303,6 +310,13 @@ static gboolean _d2ds_dbus_handle_disable(Enabler *object,
        /* Make response first */\r
        enabler_complete_disable(object, invocation, ret);\r
 \r
+       /* De-Intialize subowner client */\r
+       ret = d2ds_request_disable(service);\r
+       if (D2DS_ERROR_NONE != ret) {\r
+               D2DS_LOGE("d2ds_request_disable() Fail(%d)", ret);\r
+               return FALSE;\r
+       }\r
+\r
        /* Terminate daemon */\r
        d2ds_service_exit(service);\r
 \r
index 192816ea8c4343ab5715f075d4b0f19a58ba9c8d..06710b81094eca01e7be9525b9965aa2bb2dc0ab 100644 (file)
  *****************************************************************/
 #include "iotivity_config.h"
 
+#include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#include <glib.h>
+#include <gio/gio.h>
 
 #include "platform_features.h"
 #include "utlist.h"
 
 #define MAX_FILE_PATH_LEN 1024
 
+#include "d2ds.h"
 #include "d2ds-log.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif //__cplusplus
+#include "d2ds-util.h"
 
 // declaration(s) for provisioning client using C-level provisioning API
 // user input definition for main loop on provisioning client
@@ -65,8 +65,8 @@ extern "C"
 #define ACL_RESRC_ARRAY_SIZE   3 //This value is used only for sample (not OCF spec)
 #define ACL_RESRC_MAX_LEN   128
 #define ACL_PEMISN_CNT      5
-#define DISCOVERY_TIMEOUT   5  // 5 sec
-#define CALLBACK_TIMEOUT    60  // 1 min
+#define DISCOVERY_TIMEOUT   1  // 1 sec
+#define CALLBACK_TIMEOUT    /* 100ms */ 10 * 10
 #define TAG "subownerclient"
 
 static const char* SVR_DB_FILE_NAME = "oic_svr_db_subowner_client.dat";
@@ -80,7 +80,7 @@ static const OicSecPrm_t  SUPPORTED_PRMS[1] =
 // |g_ctx| means provision manager application context and
 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
 // for accessing all function(s) for these, they are declared on global domain
-static const char* g_ctx = "SubOwner Client Application Context";
+static const char* g_ctx = "SubOwner Client Context";
 static char* g_svr_fname;
 static char* g_prvn_fname;
 static OCProvisionDev_t* g_own_list;
@@ -94,850 +94,1196 @@ static int g_mowned_cnt;
 static bool g_doneCB;
 
 // function declaration(s) for calling them before implementing
-static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
-static int printDevList(const OCProvisionDev_t*);
-static size_t printUuidList(const OCUuidList_t*);
-static int printResultList(const OCProvisionResult_t*, const int);
-static void printUuid(const OicUuid_t*);
-static FILE* fopen_prvnMng(const char*, const char*);
-static int waitCallbackRet(void);
-static int selectTwoDiffNum(int*, int*, const int, const char*);
 
-// callback function(s) for provisioning client using C-level provisioning API
-static void multipleOwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+static void _d2d_print_uuid(const OicUuid_t* uuid)
 {
-    if(!hasError)
-    {
-        D2DS_LOGD("Multiple Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
-    }
-    else
-    {
-        D2DS_LOGD( "Multiple Ownership Transfer FAILED - ctx: %s", (char*) ctx);
-        printResultList((const OCProvisionResult_t*) arr, nOfRes);
-    }
-    g_doneCB = true;
+       char uuid_string[256] = {0};
+       snprintf(uuid_string, sizeof(uuid_string),
+               "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+               (*uuid).id[0], (*uuid).id[1], (*uuid).id[2], (*uuid).id[3],
+               (*uuid).id[4], (*uuid).id[5],  (*uuid).id[6], (*uuid).id[7],
+               (*uuid).id[8], (*uuid).id[9],  (*uuid).id[10], (*uuid).id[11],
+               (*uuid).id[12], (*uuid).id[13], (*uuid).id[14], (*uuid).id[15]);
+       D2DS_LOGI("%s", uuid_string);
+}
+static OCProvisionDev_t* _get_dev_by_id(const OCProvisionDev_t* dev_lst, const int dev_num)
+{
+       if(!dev_lst || 0>=dev_num) {
+               D2DS_LOGI("     Device List is Empty..\n");
+               return NULL;
+       }
+
+       OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+       for(int i=0; lst; ) {
+               if(dev_num == ++i) {
+                       return lst;
+               }
+               lst = lst->next;
+       }
+
+    return NULL;  // in here |lst| is always |NULL|
+}
+
+static OCProvisionDev_t* _get_dev_by_uuid(const OCProvisionDev_t* dev_lst,
+       const OicUuid_t* uuid)
+{
+       if(!dev_lst ) {
+               D2DS_LOGI("dev_lst is empty");
+               return NULL;
+       }
+
+       if(!uuid ) {
+               D2DS_LOGI("uuid is NULL");
+               return NULL;
+       }
+
+       OCProvisionDev_t* lst = (OCProvisionDev_t*)dev_lst;
+       while (lst) {
+               if (!memcmp((const void *)&lst->doxm->deviceID, (const void *)uuid, sizeof(OicUuid_t)))
+                       return lst;
+               lst = lst->next;
+       }
+
+    return NULL;
+}
+
+static int printDevList(const OCProvisionDev_t* dev_lst)
+{
+       if(!dev_lst) {
+               D2DS_LOGI("     Device List is Empty..\n\n");
+               return 0;
+       }
+
+       OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+       int lst_cnt = 0;
+       for( ; lst; ) {
+               D2DS_LOGI("     [%d] ", ++lst_cnt);
+               _d2d_print_uuid((const OicUuid_t*) &lst->doxm->deviceID);
+               lst = lst->next;
+       }
+
+       return lst_cnt;
+}
+
+static size_t printUuidList(const OCUuidList_t* uid_lst)
+{
+       if(!uid_lst) {
+               D2DS_LOGI("     Device List is Empty..\n\n");
+               return 0;
+       }
+
+       OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
+       size_t lst_cnt = 0;
+       for( ; lst; ) {
+               D2DS_LOGI("     [%zu] ", ++lst_cnt);
+               _d2d_print_uuid((const OicUuid_t*) &lst->dev);
+               lst = lst->next;
+       }
+       D2DS_LOGI("\n");
+
+       return lst_cnt;
+}
+
+static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
+{
+       if(!rslt_lst || 0>=rslt_cnt) {
+               D2DS_LOGI("     Device List is Empty..\n\n");
+               return 0;
+       }
+
+       int lst_cnt = 0;
+       for( ; rslt_cnt>lst_cnt; ++lst_cnt) {
+               D2DS_LOGI("     [%d] ", lst_cnt+1);
+               _d2d_print_uuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
+               D2DS_LOGI(" - result: %d\n", rslt_lst[lst_cnt].res);
+       }
+       D2DS_LOGI("\n");
+
+       return lst_cnt;
+}
+
+static FILE*_d2ds_fopen_prvn_mng(const char* path, const char* mode)
+{
+       char data_dir[MAX_FILE_PATH_LEN] = {0,};
+
+       snprintf(data_dir, MAX_FILE_PATH_LEN, "%s/network/%s",
+                       tzplatform_getenv(TZ_SYS_GLOBALUSER_DATA), SVR_DB_FILE_NAME);
+
+       NOTUSED(path);
+#if 0
+       D2DS_LOGD("Unsed DB path  %s\n", path);
+#endif
+
+       return fopen(data_dir, mode);
+}
+
+static int ___d2d_wait_cb_ret(void)
+{
+       OCStackResult ret = OC_STACK_OK;
+       for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i) {
+               usleep(1000);
+               ret = OCProcess();
+               if(OC_STACK_OK != ret) {
+                       D2DS_LOGE( "OCStack process error = %d", ret);
+                       return ret;
+               }
+       }
+
+       if(!g_doneCB)
+               OCPDMCleanupForTimeout();
+
+       return ret;
+}
+
+#if 0 /* TEST */
+static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
+{
+       if(!a || !b || 2>max || !str) {
+               return -1;
+       }
+
+       for( ; ; ) {
+               for(int i=0; 2>i; ++i)  {
+                       int* num = 0==i?a:b;
+                       for( ; ; )  {
+                               printf("   > Enter Device[%d] Number, %s: ", i+1, str);
+                               for(int ret=0; 1!=ret; ) {
+                                       ret = scanf("%d", num);
+                                       for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                        // '0x20<=code' is character region
+                               }
+                               if(0<*num && max>=*num) {
+                                       break;
+                               }
+                               printf("     Entered Wrong Number. Please Enter Again\n");
+                       }
+               }
+               if(*a != *b) {
+                       printf("\n");
+                       return 0;
+               }
+       }
+
+       return -1;
 }
 
 // callback function(s) for provisioning client using C-level provisioning API
 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
 {
-    if(!hasError)
-    {
-        D2DS_LOGD( "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
-    }
-    else
-    {
-        D2DS_LOGD( "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
-        printResultList((const OCProvisionResult_t*) arr, nOfRes);
-    }
-    g_doneCB = true;
+       if(!hasError)
+       {
+               D2DS_LOGD( "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
+       }
+       else
+       {
+               D2DS_LOGD( "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
+               printResultList((const OCProvisionResult_t*) arr, nOfRes);
+       }
+       g_doneCB = true;
 }
 
 static void updateDoxmForMOTCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
 {
-    if(!hasError)
-    {
-        D2DS_LOGD( "POST 'doxm' SUCCEEDED - ctx: %s", (char*) ctx);
-    }
-    else
-    {
-        D2DS_LOGD( "POST 'doxm'  FAILED - ctx: %s", (char*) ctx);
-        printResultList((const OCProvisionResult_t*) arr, nOfRes);
-    }
-    g_doneCB = true;
+       if(!hasError)
+       {
+               D2DS_LOGD( "POST 'doxm' SUCCEEDED - ctx: %s", (char*) ctx);
+       }
+       else
+       {
+               D2DS_LOGD( "POST 'doxm'  FAILED - ctx: %s", (char*) ctx);
+               printResultList((const OCProvisionResult_t*) arr, nOfRes);
+       }
+       g_doneCB = true;
 }
 
 static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
 {
-    if(!hasError)
-    {
-        D2DS_LOGD( "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
-    }
-    else
-    {
-        D2DS_LOGD( "Provision Credential FAILED - ctx: %s", (char*) ctx);
-        printResultList((const OCProvisionResult_t*) arr, nOfRes);
-    }
-    g_doneCB = true;
+       if(!hasError)
+       {
+               D2DS_LOGD( "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
+       }
+       else
+       {
+               D2DS_LOGD( "Provision Credential FAILED - ctx: %s", (char*) ctx);
+               printResultList((const OCProvisionResult_t*) arr, nOfRes);
+       }
+       g_doneCB = true;
 }
 
 static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
 {
-    if(!hasError)
-    {
-        D2DS_LOGD( "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
-    }
-    else
-    {
-        D2DS_LOGD( "Provision ACL FAILED - ctx: %s", (char*) ctx);
-        printResultList((const OCProvisionResult_t*) arr, nOfRes);
-    }
-    g_doneCB = true;
+       if(!hasError)
+       {
+               D2DS_LOGD( "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
+       }
+       else
+       {
+               D2DS_LOGD( "Provision ACL FAILED - ctx: %s", (char*) ctx);
+               printResultList((const OCProvisionResult_t*) arr, nOfRes);
+       }
+       g_doneCB = true;
 }
 
 // response handler for LED requests.
 static void LedCB(void *ctx, OCDoHandle UNUSED,
                                                     OCClientResponse *clientResponse)
 {
-    if(clientResponse)
-    {
-        if(OC_STACK_OK == clientResponse->result)
-        {
-            printf("Received OC_STACK_OK from server\n");
-            if(clientResponse->payload)
-            {
-                printf("Response ===================> %s\n", clientResponse->payload);
-            }
-        }
-        else if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
-        {
-            printf("Received OC_STACK_RESOURCE_CHANGED from server\n");
-        }
-        else
-        {
-            printf("Error in response : %d\n", clientResponse->result);
-        }
-    }
-    else
-    {
-        printf("Hit the response callback but can not find response data\n");
-    }
-
-    g_doneCB = true;
+       if(clientResponse)
+       {
+               if(OC_STACK_OK == clientResponse->result)
+               {
+                       printf("Received OC_STACK_OK from server\n");
+                       if(clientResponse->payload)
+                       {
+                               printf("Response ===================> %s\n", clientResponse->payload);
+                       }
+               }
+               else if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+               {
+                       printf("Received OC_STACK_RESOURCE_CHANGED from server\n");
+               }
+               else
+               {
+                       printf("Error in response : %d\n", clientResponse->result);
+               }
+       }
+       else
+       {
+               printf("Hit the response callback but can not find response data\n");
+       }
+
+       g_doneCB = true;
 }
+#endif /* TEST */
 
 static void inputPinCB(char* pin, size_t len)
 {
-    if(!pin || OXM_RANDOM_PIN_MAX_SIZE>=len)
-    {
-        D2DS_LOGE( "inputPinCB invalid parameters");
-        return;
-    }
-
-    printf("   > INPUT PIN: ");
-    for(int ret=0; 1!=ret; )
-    {
-        ret = scanf("%32s", pin);
-        for( ; 0x20<=getchar(); );  // for removing overflow garbages
-                                    // '0x20<=code' is character region
-    }
+       if(!pin || OXM_RANDOM_PIN_MAX_SIZE>=len)
+       {
+               D2DS_LOGE( "inputPinCB invalid parameters");
+               return;
+       }
+
+       printf("   > INPUT PIN: ");
+       for(int ret=0; 1!=ret; )
+       {
+               ret = scanf("%32s", pin);
+               for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                       // '0x20<=code' is character region
+       }
 }
 
-// function(s) for provisioning client using C-level provisioning API
-static int initProvisionClient(void)
+static void _d2ds_remove_mot_client()
 {
-    // initialize persistent storage for SVR DB
-    static OCPersistentStorage ps = {fopen_prvnMng, fread, fwrite, fclose, unlink};
-    if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&ps))
-    {
-        D2DS_LOGE( "OCRegisterPersistentStorageHandler error");
-        return -1;
-    }
+       GMutex motdev_mutex;
+
+       g_mutex_init(&motdev_mutex);
+       g_mutex_lock(&motdev_mutex);
+       if(g_motdev_list) {
+               OCDeleteDiscoveredDevices(g_motdev_list);
+               g_motdev_list = NULL;
+       }
+       g_mutex_unlock(&motdev_mutex);
+}
 
-    // initialize OC stack and provisioning manager
-    if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
-    {
-        D2DS_LOGE( "OCStack init error");
-        return -1;
-    }
+static void _d2ds_remove_owned_client()
+{
+       GMutex owned_dev_mutex;
+
+       /* delete un/owned device lists before updating them */
+       g_mutex_init(&owned_dev_mutex);
+       g_mutex_lock(&owned_dev_mutex);
+       if(g_mowned_list) {
+               OCDeleteDiscoveredDevices(g_mowned_list);
+               g_mowned_list = NULL;
+       }
+       g_mutex_unlock(&owned_dev_mutex);
+}
 
-    if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
-    {
-        printf("************************************************************\n");
-        printf("************Provisioning DB file already exists.************\n");
-        printf("************************************************************\n");
-    }
-    else
-    {
-        printf("*************************************************************\n");
-        printf("************No provisioning DB file, creating new************\n");
-        printf("*************************************************************\n");
-    }
+// function(s) for provisioning client using C-level provisioning API
+static int d2ds_init_provision_client(void)
+{
+       OCStackResult ret = OC_STACK_OK;
+       char data_dir[MAX_FILE_PATH_LEN] = {0,};
 
-    if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
-    {
-        D2DS_LOGE( "OC_PM init error");
-        return -1;
-    }
+       snprintf(data_dir, MAX_FILE_PATH_LEN, "%s/network/%s",
+                       tzplatform_getenv(TZ_SYS_GLOBALUSER_DATA), PRVN_DB_FILE_NAME);
+
+       // initialize persistent storage for SVR DB
+       static OCPersistentStorage ps = {
+                       _d2ds_fopen_prvn_mng,
+                       fread,
+                       fwrite,
+                       fclose,
+                       unlink
+                       };
+
+       ret = OCRegisterPersistentStorageHandler(&ps);
+       if(OC_STACK_OK != ret ) {
+               D2DS_LOGE( "OCRegisterPersistentStorageHandler error = %d", ret);
+               return -1;
+       }
+
+       // initialize OC stack and provisioning manager
+       ret = OCInit(NULL, 0, OC_CLIENT_SERVER);
+       if(OC_STACK_OK != ret ) {
+               D2DS_LOGE( "OCInit() error = %d", ret);
+               return -1;
+       }
+
+       if (access(data_dir, F_OK) != -1)
+               D2DS_LOGI("Provisioning DB file already exists");
+       else
+               D2DS_LOGI("No provisioning DB file, creating new");
+
+       ret = OCInitPM(data_dir);
+       if(OC_STACK_OK != ret ) {
+               D2DS_LOGE( "OCInitPM() error = %d", ret);
+               return -1;
+       }
+
+       SetInputPinCB(inputPinCB);
+
+       return ret;
+}
 
-    SetInputPinCB(inputPinCB);
+/* command id */
+typedef enum {
+       D2DS_DISC_MOT_ENB_DEVS = 0,
+       D2DS_DISC_MOTED_DEVS,
+       D2DS_MOT,
+       D2DS_MOT_PAIRWISE,
+} d2ds_cmd_id_e;
+
+typedef struct {
+       d2ds_cmd_id_e cid; /**< Command ID */
+       int tid; /**< Timer ID */
+       GThread *thread; /**< Thread handle */
+       unsigned int sid; /**< Subcribed signal ID */
+       bool found; /**< Whether we discoverd devices */
+       void *cb; /**< Callback function pointer */
+       void *userdata; /**< User data */
+
+       OCProvisionDev_t *target; /**< Target device */
+       guchar *pin /**< PIN */
+
+} d2ds_req_cb_s;
+
+static void _d2sd_request_cleanup(gpointer data)
+{
+       d2ds_req_cb_s *con = (d2ds_req_cb_s *)data;
+       d2ds_service *service = (d2ds_service *)con->userdata;
+
+       if (con->tid) {
+               g_source_remove(con->tid);
+               con->tid = 0;
+       }
+       con->sid = 0;
+       con->found = FALSE;
+       if (con->target)
+               PMDeleteDeviceList(con->target);
+       if (con->pin)
+               free(con->pin);
+
+       /* Set d2ds status 'pending' */
+       g_atomic_int_set(&service->pending, 0);
+
+       free(con);
+}
 
-    return 0;
+static gboolean _d2ds_timeout_cb(gpointer p)
+{
+       d2ds_req_cb_s *con = (d2ds_req_cb_s *)p;
+
+       if (NULL == con, G_SOURCE_REMOVE) {
+               D2DS_LOGE("container is NULL");
+               return G_SOURCE_REMOVE;
+       }
+       if (con->found) {
+               D2DS_LOGE("cb was alreay handled");
+               return G_SOURCE_REMOVE;
+       }
+
+       if(OC_STACK_OK != OCProcess()) {
+               D2DS_LOGE( "OCStack process error");
+               return G_SOURCE_REMOVE;
+       }
+
+       OCPDMCleanupForTimeout();
+
+       switch (con->cid) {
+               case D2DS_DISC_MOT_ENB_DEVS:
+                       // display the discovered device lists
+                       D2DS_LOGE("   > Discovered Multiple Ownership Transfer Enabled Devices\n");
+                       g_motdev_cnt = printDevList(g_motdev_list);
+                       break;
+               case D2DS_DISC_MOTED_DEVS:
+                       break;
+               case D2DS_MOT:
+                       break;
+               case D2DS_MOT_PAIRWISE:
+                       break;
+       }
+
+       _d2sd_request_cleanup((gpointer)con);
+
+       return G_SOURCE_REMOVE;
 }
 
-static int discoverMotSupportedDevices(void)
+#ifdef TIMER_TEST
+static int _d2ds_disc_mot_enb_devs_timer(d2ds_service *service)
 {
-    // delete un/owned device lists before updating them
-    if(g_motdev_list)
-    {
-        OCDeleteDiscoveredDevices(g_motdev_list);
-        g_motdev_list = NULL;
-    }
+       d2ds_req_cb_s *con = NULL;
+
+       _d2ds_remove_mot_client();
+
+       // call |OCDiscoverMultipleOwnerEnabledDevices| API actually
+       D2DS_LOGI("   Discovering Multiple Ownership Transfer enabled Devices on Network..\n");
+       if(OC_STACK_OK != OCDiscoverMultipleOwnerEnabledDevices(DISCOVERY_TIMEOUT,
+               &g_motdev_list)) {
+               D2DS_LOGE( "OCDiscoverMultipleOwnerEnalbedDevices API error");
+               return D2DS_ERROR_OPERATION_FAILED;
+       }
+
+       con = calloc(1, sizeof(d2ds_req_cb_s));
+       if (NULL == con) {
+               D2DS_LOGE( "calloc() Fail=%d", errno);
+               return D2DS_ERROR_OUT_OF_MEMORY;
+       }
+
+       //con->cb = cb;
+       //con->sid = sub_id;
+       con->userdata = service;
+       con->cid = D2DS_DISC_MOT_ENB_DEVS;
+       con->tid = g_timeout_add_seconds(DISCOVERY_TIMEOUT + 1, _d2ds_timeout_cb, con);
+
+       return D2DS_ERROR_NONE;
+}
+#endif
 
-    // call |OCDiscoverMultipleOwnerEnabledDevices| API actually
-    printf("   Discovering Multiple Ownership Transfer enabled Devices on Network..\n");
-    if(OC_STACK_OK != OCDiscoverMultipleOwnerEnabledDevices(DISCOVERY_TIMEOUT, &g_motdev_list))
-    {
-        D2DS_LOGE( "OCDiscoverMultipleOwnerEnalbedDevices API error");
-        return -1;
-    }
+static gpointer __d2ds_disc_mot_env_devs_func(gpointer data)
+{
+       NOTUSED(data);
 
-    // display the discovered device lists
-    printf("   > Discovered Multiple Ownership Transfer Enabled Devices\n");
-    g_motdev_cnt = printDevList(g_motdev_list);
+       /* delete un/owned device lists before updating them */
+       _d2ds_remove_mot_client();
 
-    return 0;
-}
+       // call |OCDiscoverMultipleOwnerEnabledDevices| API actually
+       D2DS_LOGI("   Discovering Multiple Ownership Transfer enabled Devices on Network..\n");
+       if(OC_STACK_OK != OCDiscoverMultipleOwnerEnabledDevices(DISCOVERY_TIMEOUT,
+               &g_motdev_list)) {
+               D2DS_LOGE( "OCDiscoverMultipleOwnerEnalbedDevices API error");
+               return NULL;
+       }
 
-static int discoverSubOwnerDevices()
-{
-    // delete un/owned device lists before updating them
-    if(g_mowned_list)
-    {
-        OCDeleteDiscoveredDevices(g_mowned_list);
-        g_mowned_list = NULL;
-    }
+       g_thread_exit(GINT_TO_POINTER (1));
 
-    // call |OCDiscoverMultipleOwnedDevices| API actually
-    printf("   Discovering Multiple Owned Devices on Network..\n");
-    if(OC_STACK_OK != OCDiscoverMultipleOwnedDevices(DISCOVERY_TIMEOUT, &g_mowned_list))
-    {
-        D2DS_LOGE( "OCDiscoverMultipleOwnerEnabledDevices API error");
-        return -1;
-    }
+       _d2sd_request_cleanup((gpointer)data);
 
-    // display the discovered device lists
-    printf("   > Discovered Multiple Owned Devices\n");
-    g_mowned_cnt = printDevList(g_mowned_list);
+       return NULL;
+}
 
-    return 0;
+static int _d2ds_disc_mot_enb_devs_thd(d2ds_service *service)
+{
+       d2ds_req_cb_s *con = NULL;
+       con = calloc(1, sizeof(d2ds_req_cb_s));
+       if (NULL == con) {
+               D2DS_LOGE( "calloc() Fail=%d", errno);
+               return D2DS_ERROR_OUT_OF_MEMORY;
+       }
+
+       con->thread = g_thread_try_new("disc_mot_env_devs", __d2ds_disc_mot_env_devs_func, con, NULL);
+       if (!con->thread) {
+               D2DS_LOGE("Failed to create thread");
+               return D2DS_ERROR_OUT_OF_MEMORY;
+       }
+       g_thread_unref(con->thread);
+
+       con->userdata = service;
+       con->cid = D2DS_DISC_MOT_ENB_DEVS;
+       con->tid = g_timeout_add_seconds(DISCOVERY_TIMEOUT + 1, _d2ds_timeout_cb, con);
+
+       return D2DS_ERROR_NONE;
 }
 
-static int multipleOwnershipTransfer(void)
+static gpointer __d2ds_disc_owned_env_devs_func(gpointer data)
 {
-    // check |unown_list| for registering devices
-    if(!g_motdev_list || 0 >=g_motdev_cnt)
-    {
-        printf("   > MultipleOwnershipTransfer Enabled Device List is Empty\n");
-        printf("   > Please Discover Devices first, with [10] Menu\n");
-        return 0;  // normal case
-    }
+       NOTUSED(data);
 
-    // call |getDevInst| API actually
-    // calling this API with callback actually acts like blocking
-    // for error checking, the return value saved and printed
-    g_doneCB = false;
+       // delete un/owned device lists before updating them
+       _d2ds_remove_owned_client();
 
-#ifdef MULTIPLE_OWNER
-    OCProvisionDev_t* dev = NULL;
-    LL_FOREACH(g_motdev_list, dev)
-    {
-        if(OIC_PRECONFIG_PIN == dev->doxm->oxmSel)
-        {
-            //Pre-Configured PIN initialization
-            const char* testPreconfigPin = "12341234";
-            if(OC_STACK_OK != OCAddPreconfigPin(dev, testPreconfigPin, strlen(testPreconfigPin)))
-            {
-                printf("\n\n\n*** %60s ***\n", "WARNNING : Failed to save the pre-configured PIN");
-                printf("*** %60s ***\n\n\n", "WARNNING : You can't use the pre-configured PIN OxM for MOT");
-                return -1;
-            }
-        }
-    }
-#endif //MULTIPLE_OWNER
+       // call |OCDiscoverMultipleOwnedDevices| API actually
+       printf("   Discovering Multiple Owned Devices on Network..\n");
+       if(OC_STACK_OK != OCDiscoverMultipleOwnedDevices(DISCOVERY_TIMEOUT, &g_mowned_list))
+       {
+               D2DS_LOGE( "OCDiscoverMultipleOwnerEnabledDevices API error");
+               return NULL;
+       }
 
-    if(OC_STACK_OK != OCDoMultipleOwnershipTransfer(g_ctx, g_motdev_list, multipleOwnershipTransferCB))
-    {
-        D2DS_LOGE( "_20_PERFORM_MOT_: error");
-        return -1;
-    }
+       // display the discovered device lists
+       printf("   > Discovered Multiple Owned Devices\n");
+       g_mowned_cnt = printDevList(g_mowned_list);
 
-    if(waitCallbackRet())  // input |g_doneCB| flag implicitly
-    {
-        D2DS_LOGE( "OCProvisionCredentials callback error");
-        return -1;
-    }
+       _d2sd_request_cleanup(data);
 
-    // display the registered result
-    printf("   > Registered Discovered Devices\n");
+       return NULL;
+}
 
-    return 0;
+static int _d2ds_disc_owned_devs(d2ds_service *service)
+{
+       d2ds_req_cb_s *con = NULL;
+       con = calloc(1, sizeof(d2ds_req_cb_s));
+       if (NULL == con) {
+               D2DS_LOGE( "calloc() Fail=%d", errno);
+               return D2DS_ERROR_OUT_OF_MEMORY;
+       }
+
+       con->thread = g_thread_try_new("disc_owned_devs", __d2ds_disc_owned_env_devs_func, con, NULL);
+       if (!con->thread) {
+               D2DS_LOGE("Failed to create thread");
+               return D2DS_ERROR_OUT_OF_MEMORY;
+       }
+       g_thread_unref(con->thread);
+
+       con->userdata = service;
+       con->cid = D2DS_DISC_MOTED_DEVS;
+       con->tid = g_timeout_add_seconds(DISCOVERY_TIMEOUT + 1, _d2ds_timeout_cb, con);
+
+       return D2DS_ERROR_NONE;
 }
 
-static int sendGetLed()
+// callback function(s) for provisioning client using C-level provisioning API
+static void ___d2ds_mot_cb(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
 {
-    int selDevNum;
-    char query[256] = {0};
-    OCCallbackData cbData;
-    cbData.cb = &LedCB;
-    cbData.context = NULL;
-    cbData.cd = NULL;
+       if(!hasError)  {
+               D2DS_LOGD("Multiple Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
+       } else {
+               D2DS_LOGD( "Multiple Ownership Transfer FAILED - ctx: %s", (char*) ctx);
+               printResultList((const OCProvisionResult_t*) arr, nOfRes);
+       }
+       g_doneCB = true;
+}
 
-    printDevList(g_mowned_list);
+static gpointer __d2ds_mot_func(gpointer data)
+{
+       OCStackResult ret = OC_STACK_OK;
+       d2ds_req_cb_s *con = (d2ds_req_cb_s *)data;
+
+       if(!con->target)        {
+               D2DS_LOGE("Target device is NULL");
+               return NULL;
+       }
+       // call |getDevInst| API actually
+       // calling this API with callback actually acts like blocking
+       // for error checking, the return value saved and printed
+       g_doneCB = false;
 
-    // select device for provisioning access control list
-    for( ; ; )
-    {
-        printf("   > Enter Device Number, for sending GET LED request: ");
-        for(int ret=0; 1!=ret; )
-        {
-            ret = scanf("%d", &selDevNum);
-            for( ; 0x20<=getchar(); );  // for removing overflow garbages
-                                        // '0x20<=code' is character region
-        }
-        if(0<selDevNum && g_mowned_cnt>=selDevNum)
-        {
-            break;
-        }
-        printf("     Entered Wrong Number. Please Enter Again\n");
-    }
+#ifdef MULTIPLE_OWNER
+       OCProvisionDev_t* dev = NULL;
+       LL_FOREACH(con->target, dev) {
+               if(OIC_PRECONFIG_PIN == dev->doxm->oxmSel) {
+                       //Pre-Configured PIN initialization
+                       const char* testPreconfigPin = con->pin;//"12341234";
+                       if(OC_STACK_OK != OCAddPreconfigPin(dev, testPreconfigPin, strlen(testPreconfigPin))) {
+                               D2DS_LOGE("Failed to save the pre-configured PIN");
+                               D2DS_LOGE("You can't use the pre-configured PIN OxM for MOT");
+                               return NULL;
+                       }
+               }
+       }
+#endif //MULTIPLE_OWNER
+       ret = OCDoMultipleOwnershipTransfer(g_ctx, con->target, ___d2ds_mot_cb);
+       if(OC_STACK_OK != ret )  {
+               D2DS_LOGE( "OCDoMultipleOwnershipTransfer: ret=%d", ret);
+               return NULL;
+       }
 
-    OCProvisionDev_t* selDev = getDevInst(g_mowned_list, selDevNum);
-    if(NULL == selDev)
-    {
-        printf("Failed to getDevInst()\n");
-        return -1;
-    }
+       ret = ___d2d_wait_cb_ret();
+       if(ret)  {
+               D2DS_LOGE( "OCProvisionCredentials callback error = %d", ret);
+               return NULL;
+       }
 
-    if(PMGenerateQuery(true, selDev->endpoint.addr, selDev->securePort, selDev->connType,
-                       query, sizeof(query), "/a/led"))
-    {
-        g_doneCB = false;
-        printf("query=%s\n", query);
-        if(OC_STACK_OK != OCDoResource(NULL, OC_REST_GET, query, NULL, NULL, selDev->connType,
-                                       OC_HIGH_QOS, &cbData, NULL, 0))
-        {
-            printf("********************************\n");
-            printf("Failed to send GET request to %s\n", query);
-            printf("********************************\n");
-            g_doneCB = true;
-            return -1;
-        }
+       // display the registered result
+       D2DS_LOGE("   > Registered Discovered Devices\n");
 
-        waitCallbackRet();
-    }
-    else
-    {
-        printf("Failed to generate GET request for /a/led\n");
-        return -1;
-    }
+       _d2sd_request_cleanup(data);
 
-    return 0;
+       return NULL;
 }
 
-static int sendPutLed()
+OicUuid_t* __d2ds_convert_uuid(const gchar *device_id)
 {
-    int selDevNum;
-    char query[256] = {0};
-    OCCallbackData cbData;
-    cbData.cb = &LedCB;
-    cbData.context = NULL;
-    cbData.cd = NULL;
-
-    printDevList(g_mowned_list);
-    // select device for provisioning access control list
-    for( ; ; )
-    {
-        printf("   > Enter Device Number, for sending PUT LED request: ");
-        for(int ret=0; 1!=ret; )
-        {
-            ret = scanf("%d", &selDevNum);
-            for( ; 0x20<=getchar(); );  // for removing overflow garbages
-                                        // '0x20<=code' is character region
-        }
-        if(0<selDevNum && g_mowned_cnt>=selDevNum)
-        {
-            break;
-        }
-        printf("     Entered Wrong Number. Please Enter Again\n");
-    }
+       OicUuid_t *uuid;
+
+       if (NULL == device_id)
+               return NULL;
+
+       uuid = calloc(1, sizeof(struct OicUuid));
+       if (NULL == uuid) {
+               D2DS_LOGE("calloc() Fail(%d)", errno);
+               return NULL;
+       }
+
+       sscanf(&device_id[0], "%2hhx", &uuid->id[0]);
+       sscanf(&device_id[2], "%2hhx", &uuid->id[1]);
+       sscanf(&device_id[4], "%2hhx", &uuid->id[2]);
+       sscanf(&device_id[6], "%2hhx", &uuid->id[3]);
+       /* device_id[8] == '-' */
+       sscanf(&device_id[9], "%2hhx", &uuid->id[4]);
+       sscanf(&device_id[11], "%2hhx", &uuid->id[5]);
+       /* device_id[13] == '-' */
+       sscanf(&device_id[14], "%2hhx", &uuid->id[6]);
+       sscanf(&device_id[16], "%2hhx", &uuid->id[7]);
+       /* device_id[18] == '-' */
+       sscanf(&device_id[19], "%2hhx", &uuid->id[8]);
+       sscanf(&device_id[21], "%2hhx", &uuid->id[9]);
+       /* device_id[23] == '-' */
+       sscanf(&device_id[24], "%2hhx", &uuid->id[10]);
+       sscanf(&device_id[26], "%2hhx", &uuid->id[11]);
+       sscanf(&device_id[28], "%2hhx", &uuid->id[12]);
+       sscanf(&device_id[30], "%2hhx", &uuid->id[13]);
+       sscanf(&device_id[32], "%2hhx", &uuid->id[14]);
+       sscanf(&device_id[34], "%2hhx", &uuid->id[15]);
 
-    OCProvisionDev_t* selDev = getDevInst(g_mowned_list, selDevNum);
-    if(NULL == selDev)
-    {
-        printf("Failed to getDevInst()\n");
-        return -1;
-    }
+#if 0
+       D2DS_LOGE("device_id : %s", device_id);
+       _d2d_print_uuid(uuid);
+#endif
+       return uuid;
+}
 
-    if(PMGenerateQuery(true, selDev->endpoint.addr, selDev->securePort, selDev->connType,
-                       query, sizeof(query), "/a/led"))
-    {
-        g_doneCB = false;
-        printf("query=%s\n", query);
-        if(OC_STACK_OK != OCDoResource(NULL, OC_REST_PUT, query, NULL, NULL, selDev->connType,
-                                       OC_LOW_QOS, &cbData, NULL, 0))
-        {
-            printf("********************************\n");
-            printf("Failed to send PUT request to %s\n", query);
-            printf("********************************\n");
-            g_doneCB = true;
-            return -1;
-        }
 
-        waitCallbackRet();
-    }
-    else
-    {
-        printf("Failed to generate PUT request for /a/led\n");
-        return -1;
-    }
+static int _d2ds_mot(d2ds_service *service, gchar *uuid_str, gchar *pin)
+{
+       OicUuid_t *uuid = NULL;
+       OCProvisionDev_t *src_dev = NULL;
+
+       d2ds_req_cb_s *con = NULL;
+       con = calloc(1, sizeof(d2ds_req_cb_s));
+       if (NULL == con) {
+               D2DS_LOGE( "calloc() Fail=%d", errno);
+               /* Unset d2ds status 'pending' */
+               g_atomic_int_set(&service->pending, 0);
+               return D2DS_ERROR_OUT_OF_MEMORY;
+       }
+
+       uuid = __d2ds_convert_uuid(uuid_str);
+       src_dev = _get_dev_by_uuid(g_motdev_list, uuid);
+       if (!src_dev) {
+               D2DS_LOGE("We can't find in MOT dev list");
+               /* Unset d2ds status 'pending' */
+               g_atomic_int_set(&service->pending, 0);
+               return D2DS_ERROR_NO_DATA;
+       }
+
+       /* Copy target device & PIN */
+       con->target = PMCloneOCProvisionDev(src_dev);
+       /* To do MOT only one */
+       con->target->next = NULL;
+
+       if (pin) {
+               con->pin = calloc(1, OXM_RANDOM_PIN_MAX_SIZE+1);
+               if (!pin) {
+                       D2DS_LOGE("Failed to allocate PIN number");
+                       /* Unset d2ds status 'pending' */
+                       g_atomic_int_set(&service->pending, 0);
+                       return D2DS_ERROR_OUT_OF_MEMORY;
+               }
+               memcpy(con->pin, pin, OXM_RANDOM_PIN_MAX_SIZE);
+       }
+
+       con->userdata = service;
+       con->cid = D2DS_MOT;
+
+       con->thread = g_thread_try_new("mot", __d2ds_mot_func, con, NULL);
+       if (!con->thread) {
+               D2DS_LOGE("Failed to create thread");
+               /* Unset d2ds status 'pending' */
+               g_atomic_int_set(&service->pending, 0);
+               return D2DS_ERROR_OUT_OF_MEMORY;
+       }
+       g_thread_unref(con->thread);
+
+       con->tid = g_timeout_add_seconds(DISCOVERY_TIMEOUT + 1, _d2ds_timeout_cb, con);
+
+       return D2DS_ERROR_NONE;
+}
 
-    return 0;
+#if 0 /* TEST */
+static int sendGetLed()
+{
+       int selDevNum;
+       char query[256] = {0};
+       OCCallbackData cbData;
+       cbData.cb = &LedCB;
+       cbData.context = NULL;
+       cbData.cd = NULL;
+
+       printDevList(g_mowned_list);
+
+       // select device for provisioning access control list
+       for( ; ; )
+       {
+               printf("   > Enter Device Number, for sending GET LED request: ");
+               for(int ret=0; 1!=ret; )
+               {
+                       ret = scanf("%d", &selDevNum);
+                       for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                               // '0x20<=code' is character region
+               }
+               if(0<selDevNum && g_mowned_cnt>=selDevNum)
+               {
+                       break;
+               }
+               printf("     Entered Wrong Number. Please Enter Again\n");
+       }
+
+       OCProvisionDev_t* selDev = _get_dev_by_id(g_mowned_list, selDevNum);
+       if(NULL == selDev)
+       {
+               printf("Failed to _get_dev_by_id()\n");
+               return -1;
+       }
+
+       if(PMGenerateQuery(true, selDev->endpoint.addr, selDev->securePort, selDev->connType,
+               query, sizeof(query), "/a/led"))
+       {
+               g_doneCB = false;
+               printf("query=%s\n", query);
+               if(OC_STACK_OK != OCDoResource(NULL, OC_REST_GET, query, NULL, NULL, selDev->connType,
+               OC_HIGH_QOS, &cbData, NULL, 0))
+               {
+                       printf("********************************\n");
+                       printf("Failed to send GET request to %s\n", query);
+                       printf("********************************\n");
+                       g_doneCB = true;
+                       return -1;
+               }
+
+               waitCallbackRet();
+       }
+       else
+       {
+               printf("Failed to generate GET request for /a/led\n");
+               return -1;
+       }
+
+       return 0;
 }
 
+static int sendPutLed()
+{
+       int selDevNum;
+       char query[256] = {0};
+       OCCallbackData cbData;
+       cbData.cb = &LedCB;
+       cbData.context = NULL;
+       cbData.cd = NULL;
+
+       printDevList(g_mowned_list);
+       // select device for provisioning access control list
+       for( ; ; )
+       {
+               printf("   > Enter Device Number, for sending PUT LED request: ");
+               for(int ret=0; 1!=ret; )
+               {
+                       ret = scanf("%d", &selDevNum);
+                       for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                               // '0x20<=code' is character region
+               }
+               if(0<selDevNum && g_mowned_cnt>=selDevNum)
+               {
+                       break;
+               }
+               printf("     Entered Wrong Number. Please Enter Again\n");
+       }
+
+       OCProvisionDev_t* selDev = _get_dev_by_id(g_mowned_list, selDevNum);
+       if(NULL == selDev)
+       {
+               printf("Failed to _get_dev_by_id()\n");
+               return -1;
+       }
+
+       if(PMGenerateQuery(true, selDev->endpoint.addr, selDev->securePort, selDev->connType, query,
+               sizeof(query), "/a/led"))
+       {
+               g_doneCB = false;
+               D2DS_LOGI("query=%s\n", query);
+               if(OC_STACK_OK != OCDoResource(NULL, OC_REST_PUT, query, NULL, NULL, selDev->connType,
+                       OC_LOW_QOS, &cbData, NULL, 0))
+               {
+                       D2DS_LOGI("********************************\n");
+                       D2DS_LOGI("Failed to send PUT request to %s\n", query);
+                       D2DS_LOGI("********************************\n");
+                       g_doneCB = true;
+                       return -1;
+               }
+
+               waitCallbackRet();
+       }
+       else
+       {
+               printf("Failed to generate PUT request for /a/led\n");
+               return -1;
+       }
+
+       return 0;
+}
 
 static OicSecAcl_t* createAclForLEDAccess(const OicUuid_t* subject)
 {
-    if(NULL == subject)
-    {
-        D2DS_LOGE( "createAcl: Invalid paramters");
-        return NULL;
-    }
-    // allocate memory for |acl| struct
-    OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
-    if(!acl)
-    {
-        D2DS_LOGE( "createAcl: OICCalloc error return");
-        return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
-    }
-    OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
-    if(!ace)
-    {
-        D2DS_LOGE( "createAcl: OICCalloc error return");
-        return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
-    }
-    LL_APPEND(acl->aces, ace);
-    memcpy(ace->subjectuuid.id, subject->id, sizeof(subject->id));
-
-    // fill the href
-    char* rsrc_in = "/a/led";  // '1' for null termination
-    OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
-    if(!rsrc)
-    {
-        D2DS_LOGE( "createAcl: OICCalloc error return");
-        goto CRACL_ERROR;
-    }
-
-    size_t len = strlen(rsrc_in)+1;  // '1' for null termination
-    rsrc->href = (char*) OICCalloc(len, sizeof(char));
-    if(!rsrc->href)
-    {
-        D2DS_LOGE( "createAcl: OICCalloc error return");
-        goto CRACL_ERROR;
-    }
-    OICStrcpy(rsrc->href, len, rsrc_in);
-
-    //fill the resource type (rt)
-    rsrc->typeLen = 1;
-    rsrc->types = (char**)OICCalloc(1, sizeof(char*));
-    if(!rsrc->types)
-    {
-        D2DS_LOGE( "createAcl: OICCalloc error return");
-        goto CRACL_ERROR;
-    }
-    rsrc->types[0] = OICStrdup("oic.r.core");
-    if(!rsrc->types[0])
-    {
-        D2DS_LOGE( "createAcl: OICStrdup error return");
-        goto CRACL_ERROR;
-    }
-
-    //fill the interface (if)
-    rsrc->interfaceLen = 1;
-    rsrc->interfaces = (char**)OICCalloc(1, sizeof(char*));
-    if(!rsrc->interfaces)
-    {
-        D2DS_LOGE( "createAcl: OICCalloc error return");
-        goto CRACL_ERROR;
-    }
-    rsrc->interfaces[0] = OICStrdup("oic.if.baseline");
-    if(!rsrc->interfaces[0])
-    {
-        D2DS_LOGE( "createAcl: OICStrdup error return");
-        goto CRACL_ERROR;
-    }
-
-    LL_APPEND(ace->resources, rsrc);
-
-    // full permission for /a/led
-    ace->permission = PERMISSION_FULL_CONTROL;
-
-    ace->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
-    if(NULL == ace->eownerID)
-    {
-        D2DS_LOGE( "createAcl: OICCalloc error return");
-        goto CRACL_ERROR;
-    }
-
-    memcpy(ace->eownerID->id, subject->id, sizeof(subject->id));
-
-    return acl;
+       if(NULL == subject)
+       {
+               D2DS_LOGE( "createAcl: Invalid paramters");
+               return NULL;
+       }
+       // allocate memory for |acl| struct
+       OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
+       if(!acl)
+       {
+               D2DS_LOGE( "createAcl: OICCalloc error return");
+               return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
+       }
+       OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
+       if(!ace)
+       {
+               D2DS_LOGE( "createAcl: OICCalloc error return");
+               return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
+       }
+       LL_APPEND(acl->aces, ace);
+       memcpy(ace->subjectuuid.id, subject->id, sizeof(subject->id));
+
+       // fill the href
+       char* rsrc_in = "/a/led";  // '1' for null termination
+       OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
+       if(!rsrc)
+       {
+               D2DS_LOGE( "createAcl: OICCalloc error return");
+               goto CRACL_ERROR;
+       }
+
+       size_t len = strlen(rsrc_in)+1;  // '1' for null termination
+       rsrc->href = (char*) OICCalloc(len, sizeof(char));
+       if(!rsrc->href)
+       {
+               D2DS_LOGE( "createAcl: OICCalloc error return");
+               goto CRACL_ERROR;
+       }
+       OICStrcpy(rsrc->href, len, rsrc_in);
+
+       //fill the resource type (rt)
+       rsrc->typeLen = 1;
+       rsrc->types = (char**)OICCalloc(1, sizeof(char*));
+       if(!rsrc->types)
+       {
+               D2DS_LOGE( "createAcl: OICCalloc error return");
+               goto CRACL_ERROR;
+       }
+       rsrc->types[0] = OICStrdup("oic.r.core");
+       if(!rsrc->types[0])
+       {
+               D2DS_LOGE( "createAcl: OICStrdup error return");
+               goto CRACL_ERROR;
+       }
+
+       //fill the interface (if)
+       rsrc->interfaceLen = 1;
+       rsrc->interfaces = (char**)OICCalloc(1, sizeof(char*));
+       if(!rsrc->interfaces)
+       {
+               D2DS_LOGE( "createAcl: OICCalloc error return");
+               goto CRACL_ERROR;
+       }
+       rsrc->interfaces[0] = OICStrdup("oic.if.baseline");
+       if(!rsrc->interfaces[0])
+       {
+               D2DS_LOGE( "createAcl: OICStrdup error return");
+               goto CRACL_ERROR;
+       }
+
+       LL_APPEND(ace->resources, rsrc);
+
+       // full permission for /a/led
+       ace->permission = PERMISSION_FULL_CONTROL;
+
+       ace->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
+       if(NULL == ace->eownerID)
+       {
+               D2DS_LOGE( "createAcl: OICCalloc error return");
+               goto CRACL_ERROR;
+       }
+
+       memcpy(ace->eownerID->id, subject->id, sizeof(subject->id));
+
+       return acl;
 
 CRACL_ERROR:
-    OCDeleteACLList(acl);  // after here |acl| points nothing
-    return NULL;
+       OCDeleteACLList(acl);  // after here |acl| points nothing
+       return NULL;
 }
 
 static int provisionAclForLed()
 {
-    OicSecAcl_t* acl = NULL;
-
-    // check |own_list| for provisioning access control list
-    if(!g_mowned_list || 1> g_mowned_cnt)
-    {
-        printf("   > MOT Device List is Empty\n");
-        printf("   > Please Perform MOT first, with [12|21] Menu\n");
-        return 0;  // normal case
-    }
-
-    // display the MOT dev list
-    printf("   > MOT Devices\n");
-    g_mowned_cnt = printDevList(g_mowned_list);
-
-    // select device for provisioning access control list
-    int dev_num = 0;
-    for( ; ; )
-    {
-        printf("   > Enter Device Number, for Provisioning LED's ACL: ");
-        for(int ret=0; 1!=ret; )
-        {
-            ret = scanf("%d", &dev_num);
-            for( ; 0x20<=getchar(); );  // for removing overflow garbages
-                                        // '0x20<=code' is character region
-        }
-        if(0<dev_num && g_mowned_list>=dev_num)
-        {
-            break;
-        }
-        printf("     Entered Wrong Number. Please Enter Again\n");
-    }
-
-    g_doneCB = false;
-    printf("   Provisioning Selected ACL..\n");
-    OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_mowned_list, dev_num);
-    if(!dev)
-    {
-        D2DS_LOGE( "provisionAcl: device instance empty");
-        goto PVACL_ERROR;
-    }
-
-    acl = createAclForLEDAccess(&dev->doxm->subOwners->uuid);
-    if(NULL == acl)
-    {
-        D2DS_LOGE( "provisionAcl: Failed to create ACL for LED");
-        return -1;
-    }
-
-    OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
-    if(OC_STACK_OK != rst)
-    {
-        D2DS_LOGD( "OCProvisionACL API error: %d", rst);
-        goto PVACL_ERROR;
-    }
-    if(waitCallbackRet())  // input |g_doneCB| flag implicitly
-    {
-        D2DS_LOGE( "OCProvisionCredentials callback error");
-        goto PVACL_ERROR;
-    }
-    // display the ACL-provisioned result
-    printf("   > Provisioned Selected ACL\n");
-
-    OCDeleteACLList(acl);  // after here |acl| points nothing
-    return 0;
+       OicSecAcl_t* acl = NULL;
+
+       // check |own_list| for provisioning access control list
+       if(!g_mowned_list || 1> g_mowned_cnt)
+       {
+               printf("   > MOT Device List is Empty\n");
+               printf("   > Please Perform MOT first, with [12|21] Menu\n");
+               return 0;  // normal case
+       }
+
+       // display the MOT dev list
+       printf("   > MOT Devices\n");
+       g_mowned_cnt = printDevList(g_mowned_list);
+
+       // select device for provisioning access control list
+       int dev_num = 0;
+       for( ; ; )
+       {
+               printf("   > Enter Device Number, for Provisioning LED's ACL: ");
+               for(int ret=0; 1!=ret; )
+               {
+                       ret = scanf("%d", &dev_num);
+                       for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                       // '0x20<=code' is character region
+               }
+               if(0<dev_num && g_mowned_list>=dev_num)
+               {
+                       break;
+               }
+               printf("     Entered Wrong Number. Please Enter Again\n");
+       }
+
+       g_doneCB = false;
+       printf("   Provisioning Selected ACL..\n");
+       OCProvisionDev_t* dev = _get_dev_by_id((const OCProvisionDev_t*) g_mowned_list, dev_num);
+       if(!dev)
+       {
+               D2DS_LOGE( "provisionAcl: device instance empty");
+               goto PVACL_ERROR;
+       }
+
+       acl = createAclForLEDAccess(&dev->doxm->subOwners->uuid);
+       if(NULL == acl)
+       {
+               D2DS_LOGE( "provisionAcl: Failed to create ACL for LED");
+               return -1;
+       }
+
+       OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
+       if(OC_STACK_OK != rst)
+       {
+               D2DS_LOGD( "OCProvisionACL API error: %d", rst);
+               goto PVACL_ERROR;
+       }
+       if(waitCallbackRet())  // input |g_doneCB| flag implicitly
+       {
+               D2DS_LOGE( "OCProvisionCredentials callback error");
+               goto PVACL_ERROR;
+       }
+       // display the ACL-provisioned result
+       printf("   > Provisioned Selected ACL\n");
+
+       OCDeleteACLList(acl);  // after here |acl| points nothing
+       return 0;
 
 PVACL_ERROR:
-    OCDeleteACLList(acl);
-    return -1;
+       OCDeleteACLList(acl);
+       return -1;
 }
 
 static int provisionCred()
 {
-    // check |unown_list| for registering devices
-    if(!g_mowned_list|| 0 >=g_mowned_cnt)
-    {
-        printf("   > Multiple Owned Device List is Empty\n");
-        printf("   > Please Discover Devices first, with [13] Menu\n");
-        return 0;  // normal case
-    }
-
-    // display the MOT dev list
-    printf("   > Multiple Owned Devices\n");
-    g_mowned_cnt = printDevList(g_mowned_list);
-
-    int dev_num = 0;
-    for( ; ; )
-    {
-        printf("   > Enter Multiple Owned Device Number to link : ");
-        for(int ret=0; 1!=ret; )
-        {
-            ret = scanf("%d", &dev_num);
-            for( ; 0x20<=getchar(); );  // for removing overflow garbages
-                                        // '0x20<=code' is character region
-        }
-        if(0<dev_num && g_mowned_cnt>=dev_num)
-        {
-            break;
-        }
-        printf("     Entered Wrong Number. Please Enter Again\n");
-    }
-
-    OCProvisionDev_t* motDev = getDevInst(g_mowned_list, dev_num);
-    if(NULL == motDev)
-    {
-        D2DS_LOGE( "Failed to getDevInst()");
-        return -1;
-    }
-
-    // display the MOT dev list
-    printf("   > Owned Devices\n");
-    g_own_cnt = printDevList(g_own_list);
-
-    for( ; ; )
-    {
-        printf("   > Enter Owned Device Number to link : ");
-        for(int ret=0; 1!=ret; )
-        {
-            ret = scanf("%d", &dev_num);
-            for( ; 0x20<=getchar(); );  // for removing overflow garbages
-                                        // '0x20<=code' is character region
-        }
-        if(0<dev_num && g_own_cnt>=dev_num)
-        {
-            break;
-        }
-        printf("     Entered Wrong Number. Please Enter Again\n");
-    }
-
-    OCProvisionDev_t* ownDev = getDevInst(g_own_list, dev_num);
-    if(NULL == ownDev)
-    {
-        D2DS_LOGE( "Failed to getDevInst()");
-        return -1;
-    }
-
-    // call |OCProvisionCredentials| API actually
-    // calling this API with callback actually acts like blocking
-    // for error checking, the return value saved and printed
-    g_doneCB = false;
-    printf("   Provisioning Selected Pairwise Devices..\n");
-    OCStackResult rst = OCProvisionCredentials((void*) g_ctx,
-                    SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
-                    ownDev, motDev, provisionCredCB);
-    if(OC_STACK_OK != rst)
-    {
-        D2DS_LOGD( "OCProvisionPairwiseDevices API error: %d", rst);
-        goto PVPWS_ERROR;
-    }
-    if(waitCallbackRet())  // input |g_doneCB| flag implicitly
-    {
-        D2DS_LOGE( "OCProvisionCredentials callback error");
-        goto PVPWS_ERROR;
-    }
-
-    // display the pairwise-provisioned result
-    printf("   > Provisioned Selected Pairwise Devices\n");
-
-    return 0;
+       // check |unown_list| for registering devices
+       if(!g_mowned_list|| 0 >=g_mowned_cnt)
+       {
+               printf("   > Multiple Owned Device List is Empty\n");
+               printf("   > Please Discover Devices first, with [13] Menu\n");
+               return 0;  // normal case
+       }
+
+       // display the MOT dev list
+       printf("   > Multiple Owned Devices\n");
+       g_mowned_cnt = printDevList(g_mowned_list);
+
+       int dev_num = 0;
+       for( ; ; )
+       {
+               printf("   > Enter Multiple Owned Device Number to link : ");
+               for(int ret=0; 1!=ret; )
+               {
+                       ret = scanf("%d", &dev_num);
+                       for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                           // '0x20<=code' is character region
+               }
+               if(0<dev_num && g_mowned_cnt>=dev_num)
+               {
+                       break;
+               }
+               printf("     Entered Wrong Number. Please Enter Again\n");
+       }
+
+       OCProvisionDev_t* motDev = _get_dev_by_id(g_mowned_list, dev_num);
+       if(NULL == motDev)
+       {
+               D2DS_LOGE( "Failed to _get_dev_by_id()");
+               return -1;
+       }
+
+       // display the MOT dev list
+       printf("   > Owned Devices\n");
+       g_own_cnt = printDevList(g_own_list);
+
+       for( ; ; )
+       {
+               printf("   > Enter Owned Device Number to link : ");
+               for(int ret=0; 1!=ret; )
+               {
+                       ret = scanf("%d", &dev_num);
+                       for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                           // '0x20<=code' is character region
+               }
+               if(0<dev_num && g_own_cnt>=dev_num)
+               {
+                       break;
+               }
+               printf("     Entered Wrong Number. Please Enter Again\n");
+       }
+
+       OCProvisionDev_t* ownDev = _get_dev_by_id(g_own_list, dev_num);
+       if(NULL == ownDev)
+       {
+               D2DS_LOGE( "Failed to _get_dev_by_id()");
+               return -1;
+       }
+
+       // call |OCProvisionCredentials| API actually
+       // calling this API with callback actually acts like blocking
+       // for error checking, the return value saved and printed
+       g_doneCB = false;
+       printf("   Provisioning Selected Pairwise Devices..\n");
+       OCStackResult rst = OCProvisionCredentials((void*) g_ctx,
+                                               SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
+                                               ownDev, motDev, provisionCredCB);
+       if(OC_STACK_OK != rst)
+       {
+               D2DS_LOGD( "OCProvisionPairwiseDevices API error: %d", rst);
+               goto PVPWS_ERROR;
+       }
+       if(waitCallbackRet())  // input |g_doneCB| flag implicitly
+       {
+               D2DS_LOGE( "OCProvisionCredentials callback error");
+               goto PVPWS_ERROR;
+       }
+
+       // display the pairwise-provisioned result
+       printf("   > Provisioned Selected Pairwise Devices\n");
+
+       return 0;
 
 PVPWS_ERROR:
-    return -1;
-}
-
-static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
-{
-    if(!dev_lst || 0>=dev_num)
-    {
-        printf("     Device List is Empty..\n");
-        return NULL;
-    }
-
-    OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
-    for(int i=0; lst; )
-    {
-        if(dev_num == ++i)
-        {
-            return lst;
-        }
-        lst = lst->next;
-    }
-
-    return NULL;  // in here |lst| is always |NULL|
+       return -1;
 }
-
-static int printDevList(const OCProvisionDev_t* dev_lst)
+#endif /* TEST */
+int d2ds_request_enable(d2ds_service *service)
 {
-    if(!dev_lst)
-    {
-        printf("     Device List is Empty..\n\n");
-        return 0;
-    }
-
-    OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
-    int lst_cnt = 0;
-    for( ; lst; )
-    {
-        printf("     [%d] ", ++lst_cnt);
-        printUuid((const OicUuid_t*) &lst->doxm->deviceID);
-        printf("\n");
-        lst = lst->next;
-    }
-    printf("\n");
-
-    return lst_cnt;
+       int ret = D2DS_ERROR_NONE;
+       d2ds_check_null_ret_error("service", service, FALSE);
+       ret = d2ds_init_provision_client();
+       return ret;
 }
 
-static size_t printUuidList(const OCUuidList_t* uid_lst)
+int d2ds_request_disc_mot_enb_devs(d2ds_service *service)
 {
-    if(!uid_lst)
-    {
-        printf("     Device List is Empty..\n\n");
-        return 0;
-    }
+       int ret =D2DS_ERROR_NONE;
 
-    OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
-    size_t lst_cnt = 0;
-    for( ; lst; )
-    {
-        printf("     [%zu] ", ++lst_cnt);
-        printUuid((const OicUuid_t*) &lst->dev);
-        printf("\n");
-        lst = lst->next;
-    }
-    printf("\n");
+       d2ds_check_null_ret_error("service", service, FALSE);
 
-    return lst_cnt;
-}
+       D2DS_LOGD("[IPC] Discovery MOT enabled devices");
 
-static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
-{
-    if(!rslt_lst || 0>=rslt_cnt)
-    {
-        printf("     Device List is Empty..\n\n");
-        return 0;
-    }
+       /* If we are working now? */
+       if (g_atomic_int_get(&service->pending))
+               return D2DS_ERROR_IN_PROGRESS;
 
-    int lst_cnt = 0;
-    for( ; rslt_cnt>lst_cnt; ++lst_cnt)
-    {
-        printf("     [%d] ", lst_cnt+1);
-        printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
-        printf(" - result: %d\n", rslt_lst[lst_cnt].res);
-    }
-    printf("\n");
+       /* Set d2ds status 'pending' */
+       g_atomic_int_set(&service->pending, 1);
 
-    return lst_cnt;
+#ifdef TIMER_TEST
+       ret = _d2ds_disc_mot_enb_devs_timer(service);
+#else
+       ret = _d2ds_disc_mot_enb_devs_thd(service);
+#endif
+       return ret;
 }
 
-static void printUuid(const OicUuid_t* uid)
+int d2ds_request_disc_owned_devs(d2ds_service *service)
 {
-    for(int i=0; i<UUID_LENGTH; )
-    {
-        printf("%02X", (*uid).id[i++]);
-        if(i==4 || i==6 || i==8 || i==10)  // canonical format for UUID has '8-4-4-4-12'
-        {
-            printf("-");
-        }
-    }
-}
+       int ret =D2DS_ERROR_NONE;
 
-static FILE* fopen_prvnMng(const char* path, const char* mode)
-{
-    // input |g_svr_db_fname| internally by force, not using |path| parameter
-    // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
-    // with its own |SVR_DB_FILE_NAME|
-       char data_dir[MAX_FILE_PATH_LEN] = {0,};
+       d2ds_check_null_ret_error("service", service, FALSE);
 
-       snprintf(data_dir, MAX_FILE_PATH_LEN, "%s/network/%s",
-                               tzplatform_getenv(TZ_SYS_GLOBALUSER_DATA), SVR_DB_FILE_NAME);
-    (void)path;  // unused |path| parameter
+       D2DS_LOGD("[IPC] Discovery Owned devices using MOT");
 
-    return fopen(data_dir, mode);
-}
+       /* If we are working now? */
+       if (g_atomic_int_get(&service->pending))
+               return D2DS_ERROR_IN_PROGRESS;
 
-static int waitCallbackRet(void)
-{
-    for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
-    {
-        sleep(1);
-        if(OC_STACK_OK != OCProcess())
-        {
-            D2DS_LOGE( "OCStack process error");
-            return -1;
-        }
-    }
+       /* Set d2ds status 'pending' */
+       g_atomic_int_set(&service->pending, 1);
 
-    if(!g_doneCB)
-    {
-        OCPDMCleanupForTimeout();
-    }
+       ret = _d2ds_disc_owned_devs(service);
 
-    return 0;
+       return ret;
 }
 
-static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
+int d2ds_request_mot(d2ds_service *service, gchar* uuid, gchar *pin)
 {
-    if(!a || !b || 2>max || !str)
-    {
-        return -1;
-    }
-
-    for( ; ; )
-    {
-        for(int i=0; 2>i; ++i)
-        {
-            int* num = 0==i?a:b;
-            for( ; ; )
-            {
-                printf("   > Enter Device[%d] Number, %s: ", i+1, str);
-                for(int ret=0; 1!=ret; )
-                {
-                    ret = scanf("%d", num);
-                    for( ; 0x20<=getchar(); );  // for removing overflow garbages
-                                                // '0x20<=code' is character region
-                }
-                if(0<*num && max>=*num)
-                {
-                    break;
-                }
-                printf("     Entered Wrong Number. Please Enter Again\n");
-            }
-        }
-        if(*a != *b)
-        {
-            printf("\n");
-            return 0;
-        }
-    }
+       int ret =D2DS_ERROR_NONE;
 
-    return -1;
-}
+       d2ds_check_null_ret_error("service", service, FALSE);
 
-static void printMenu(void)
-{
-    printf("************************************************************\n");
-    printf("****** OIC Provisioning Client with using C-level API ******\n");
-    printf("************************************************************\n\n");
+       D2DS_LOGD("[IPC] Mullti Ownership Transfer");
 
-    printf("** [A] DISCOVER DEVICES ON NETWORK\n");
-    printf("** 10. Discover Multiple Ownership Transfer Enabled Devices on Network\n");
-    printf("** 11. Discover Multiple Owned Devices on Network\n\n");
+       /* If we are working now? */
+       if (g_atomic_int_get(&service->pending))
+               return D2DS_ERROR_IN_PROGRESS;
 
-    printf("** [B] PERFORM MULTIPLE OWNERSHIP TRANSFER\n");
-    printf("** 20. Perform the Multiple Ownership Transfer for ALL discovered dievices\n\n");
+       if (!uuid || !pin)
+               return D2DS_ERROR_INVALID_PARAMETER;
 
-    printf("** [C] Get/Put Request for APPLICATION RESOURCE\n");
-    printf("** 30. Get LED resource\n");
-    printf("** 31. Put LED resource\n\n");
+       /* Set d2ds status 'pending' */
+       g_atomic_int_set(&service->pending, 1);
 
-    printf("** [D] LINK DEVICES\n");
-    printf("** 40. Provision ACL for LED Resource\n");
-    printf("** 41. Provison Credential\n\n");
+       ret = _d2ds_mot(service, uuid, pin);
 
-    printf("** [F] EXIT PROVISIONING CLIENT\n");
-    printf("** 99. Exit Provisionong Client\n\n");
+       return ret;
+}
 
-    printf("************************************************************\n\n");
+int d2ds_request_disable(d2ds_service *service)
+{
+       d2ds_check_null_ret_error("service", service, FALSE);
+       if(OC_STACK_OK != OCStop()) {
+               D2DS_LOGE( "OCStack stop error");
+       }
+       OCDeleteDiscoveredDevices(g_own_list);  // after here |g_own_list| points nothing
+       OCDeleteDiscoveredDevices(g_unown_list);  // after here |g_unown_list| points nothing
+       OCDeleteDiscoveredDevices(g_motdev_list);  // after here |g_motdev_list| points nothing
+
+       if(g_svr_fname) {
+               OICFree(g_svr_fname);  // after here |g_svr_fname| points nothing
+       }
+       if(g_prvn_fname) {
+               OICFree(g_prvn_fname);  // after here |g_prvn_fname| points nothing
+       }
+
+       return D2DS_ERROR_NONE;
 }
+
 #if 0
 // main function for provisioning client using C-level provisioning API
 int main()
@@ -1040,7 +1386,4 @@ PMCLT_ERROR:
     return 0;  // always return normal case
 }
 #endif
-#ifdef __cplusplus
-}
-#endif //__cplusplus
 
diff --git a/src/d2d-subowner/d2ds-subowner.h b/src/d2d-subowner/d2ds-subowner.h
new file mode 100644 (file)
index 0000000..abef769
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Network Configuration Module
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. 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 __D2DS_SUBONWER_H__
+#define __D2DS_SUBONWER_H__
+
+#include "d2ds.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int d2ds_request_enable(d2ds_service *servic);
+int d2ds_request_disc_mot_enb_devs(d2ds_service *service);
+int d2ds_request_disc_owned_devs(d2ds_service *service);
+int d2ds_request_mot(d2ds_service *service, gchar* uuid, gchar *pin);
+int d2ds_request_disable(d2ds_service *service);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __D2DS_SUBONWER_H__ */
index d968adb1506e558857156bd47902d55cad4fb89c..1aa8429920a3ecdb75e9881adb227a7c954ff83d 100644 (file)
@@ -26,6 +26,7 @@
 #include "d2ds-log.h"
 #include "d2ds-util.h"
 #include "d2ds-service.h"
+#include "d2ds-service-interface.h"
 
 /**< d2d-subowner service */
 d2ds_service *d2dssvc;
@@ -58,6 +59,7 @@ int main(int argc, char *argv[])
        ret = d2ds_service_interface_init(service);
        if (G_UNLIKELY(FALSE == ret)) {
                D2DS_LOGE("Service interface init. failed!");
+               ret_code = EXIT_FAILURE;
                goto END;
        }
        /* Run d2d-subowner service */
@@ -74,6 +76,6 @@ END:
        d2dssvc = NULL;
 
        __D2DS_LOG_FUNC_EXIT__;
-       return 0;
+       return ret_code;
 }
 
index 18cd8fad11a26fc2cd99d6d5aa5ad26089930195..a7b302d1f759e645084129ccd721b138ff3374d9 100644 (file)
@@ -41,6 +41,8 @@ typedef struct _d2ds_service {
        guint dbus_id; /**< D-Bus id */\r
        guint activation_dbus_id; /**< D-Bus id for activation */\r
 \r
+       gint pending; /**< Is there any pending operation? */\r
+\r
        gpointer connection; /**< Connection handle for D-Bus call to other process */\r
        GCancellable *ca; /**< Cancellable object for D-Bus call (Daemon->other) */\r
        GList *dbus_sub_ids; /**< The list of subscribed signals */\r
index fb71434e2944228a565df6303d4343788ca8fe5e..cee1a880ebe0e5cbd7f7bdba2eeac3e333207e1e 100644 (file)
@@ -64,8 +64,8 @@ extern "C"
 #define ACL_RESRC_ARRAY_SIZE   3 //This value is used only for sample (not OCF spec)
 #define ACL_RESRC_MAX_LEN   128
 #define ACL_PEMISN_CNT      5
-#define DISCOVERY_TIMEOUT   5  // 5 sec
-#define CALLBACK_TIMEOUT    60  // 1 min
+#define DISCOVERY_TIMEOUT   5 // 5 sec
+#define CALLBACK_TIMEOUT    3  // 1 min
 #define TAG "subownerclient"
 
 static const char* SVR_DB_FILE_NAME = "oic_svr_db_subowner_client.dat";
@@ -225,6 +225,10 @@ static void inputPinCB(char* pin, size_t len)
 // function(s) for provisioning client using C-level provisioning API
 static int initProvisionClient(void)
 {
+   char data_dir[MAX_FILE_PATH_LEN] = {0,};
+
+   snprintf(data_dir, MAX_FILE_PATH_LEN, "%s/network/%s",
+               tzplatform_getenv(TZ_SYS_GLOBALUSER_DATA), PRVN_DB_FILE_NAME);
     // initialize persistent storage for SVR DB
     static OCPersistentStorage ps = {fopen_prvnMng, fread, fwrite, fclose, unlink};
     if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&ps))
@@ -240,7 +244,7 @@ static int initProvisionClient(void)
         return -1;
     }
 
-    if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
+    if (access(data_dir, F_OK) != -1)
     {
         printf("************************************************************\n");
         printf("************Provisioning DB file already exists.************\n");
@@ -253,7 +257,7 @@ static int initProvisionClient(void)
         printf("*************************************************************\n");
     }
 
-    if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
+    if(OC_STACK_OK != OCInitPM(data_dir))
     {
         D2D_LOGE( "OC_PM init error");
         return -1;
@@ -858,6 +862,7 @@ static int waitCallbackRet(void)
     for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
     {
         sleep(1);
+       printf( "waitCallbackRet : [%d]", i);
         if(OC_STACK_OK != OCProcess())
         {
             D2D_LOGE( "OCStack process error");