From: saerome.kim Date: Tue, 19 Dec 2017 04:53:16 +0000 (+0900) Subject: Implement d2d-subowner X-Git-Tag: submit/tizen/20190131.065036~287 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ccfe27b2d728a79f44778a54a111b202c4474c04;p=platform%2Fcore%2Fapi%2Fmulti-device-group.git Implement d2d-subowner - Discover MOT enabled devices - Multiple Onwership Transfer Signed-off-by: saerome.kim --- diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..139c4fb --- /dev/null +++ b/install.sh @@ -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 diff --git a/src/d2d-subowner/d2ds-log.h b/src/d2d-subowner/d2ds-log.h index 036be41..82aadd7 100644 --- a/src/d2d-subowner/d2ds-log.h +++ b/src/d2d-subowner/d2ds-log.h @@ -19,15 +19,15 @@ #ifndef __D2DS_LOG_H__ #define __D2DS_LOG_H__ -#ifdef D2DS_LOG_TAG -#undef D2DS_LOG_TAG +#ifdef LOG_TAG +#undef LOG_TAG #endif #ifdef USE_DLOG #include -#undef D2DS_LOG_TAG -#define D2DS_LOG_TAG "D2D_SUBOWNER" +#undef LOG_TAG +#define LOG_TAG "D2D_SUBOWNER" #define D2DS_LOGV(format, args...) LOGV(format, ##args) #define D2DS_LOGD(format, args...) LOGD(format, ##args) diff --git a/src/d2d-subowner/d2ds-service-interface.c b/src/d2d-subowner/d2ds-service-interface.c index 52473af..f32aa4a 100644 --- a/src/d2d-subowner/d2ds-service-interface.c +++ b/src/d2d-subowner/d2ds-service-interface.c @@ -22,6 +22,7 @@ #include "d2ds-log.h" #include "d2ds-util.h" #include "d2ds-service.h" +#include "d2ds-subowner.h" #include "d2ds-service-interface.h" #include "d2ds-generated-code.h" @@ -139,11 +140,10 @@ static gboolean _d2ds_dbus_handle_disc_mot_enb_devs(NetD2ds *object, d2ds_check_null_ret_error("service", service, FALSE); -#if 0 ret = d2ds_request_disc_mot_enb_devs(service); if (D2DS_ERROR_NONE != ret) D2DS_LOGE("Failed to d2ds_request_disc_mot_enb_devs !"); -#endif + net_d2ds_complete_disc_mot_enb_devs(object, invocation, ret); return TRUE; @@ -158,11 +158,11 @@ static gboolean _d2ds_dbus_handle_disc_moted_devs(NetD2ds *object, d2ds_check_null_ret_error("service", service, FALSE); -#if 0 - ret = d2ds_request_disc_moted_devs(service); + + ret = d2ds_request_disc_owned_devs(service); if (D2DS_ERROR_NONE != ret) - D2DS_LOGE("Failed to d2ds_request_disc_moted_devs !"); -#endif + D2DS_LOGE("Failed to d2ds_request_disc_owned_devs !"); + net_d2ds_complete_disc_moted_devs(object, invocation, ret); return TRUE; @@ -179,11 +179,11 @@ static gboolean _d2ds_dbus_handle_mot(NetD2ds *object, d2ds_check_null_ret_error("service", service, FALSE); -#if 0 - ret = d2ds_request_mot(service); + + ret = d2ds_request_mot(service, target, pin); if (D2DS_ERROR_NONE != ret) D2DS_LOGE("Failed to d2ds_request_disc_moted_devs !"); -#endif + net_d2ds_complete_mot(object, invocation, ret); return TRUE; @@ -283,6 +283,13 @@ static gboolean _d2ds_dbus_handle_enable(Enabler *object, enabler_complete_enable(object, invocation, ret); service->d2ds_activated = TRUE; + /* Intialize subowner client */ + ret = d2ds_request_enable(service); + if (D2DS_ERROR_NONE != ret) { + D2DS_LOGE("d2ds_request_enable() Fail(%d)", ret); + return FALSE; + } + /* Notify d2ds enabled */ net_d2ds_emit_subowner_enabled(d2ds_dbus_get_object(), ret); @@ -303,6 +310,13 @@ static gboolean _d2ds_dbus_handle_disable(Enabler *object, /* Make response first */ enabler_complete_disable(object, invocation, ret); + /* De-Intialize subowner client */ + ret = d2ds_request_disable(service); + if (D2DS_ERROR_NONE != ret) { + D2DS_LOGE("d2ds_request_disable() Fail(%d)", ret); + return FALSE; + } + /* Terminate daemon */ d2ds_service_exit(service); diff --git a/src/d2d-subowner/d2ds-subowner.c b/src/d2d-subowner/d2ds-subowner.c index 192816e..06710b8 100644 --- a/src/d2d-subowner/d2ds-subowner.c +++ b/src/d2d-subowner/d2ds-subowner.c @@ -19,11 +19,14 @@ *****************************************************************/ #include "iotivity_config.h" +#include #include #include #ifdef HAVE_UNISTD_H #include #endif +#include +#include #include "platform_features.h" #include "utlist.h" @@ -43,12 +46,9 @@ #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) - { - 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) - { - 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) + { + 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) + { + 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) - { - 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) + { + 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) - { - 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) - { - 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) + { + 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) + { + 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; ipending)) + 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 index 0000000..abef769 --- /dev/null +++ b/src/d2d-subowner/d2ds-subowner.h @@ -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__ */ diff --git a/src/d2d-subowner/d2ds.c b/src/d2d-subowner/d2ds.c index d968adb..1aa8429 100644 --- a/src/d2d-subowner/d2ds.c +++ b/src/d2d-subowner/d2ds.c @@ -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; } diff --git a/src/d2d-subowner/d2ds.h b/src/d2d-subowner/d2ds.h index 18cd8fa..a7b302d 100644 --- a/src/d2d-subowner/d2ds.h +++ b/src/d2d-subowner/d2ds.h @@ -41,6 +41,8 @@ typedef struct _d2ds_service { guint dbus_id; /**< D-Bus id */ guint activation_dbus_id; /**< D-Bus id for activation */ + gint pending; /**< Is there any pending operation? */ + gpointer connection; /**< Connection handle for D-Bus call to other process */ GCancellable *ca; /**< Cancellable object for D-Bus call (Daemon->other) */ GList *dbus_sub_ids; /**< The list of subscribed signals */ diff --git a/test/subownerclient.c b/test/subownerclient.c index fb71434..cee1a88 100644 --- a/test/subownerclient.c +++ b/test/subownerclient.c @@ -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");