1 /******************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 *****************************************************************/
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "ocprovisioningmanager.h"
29 #include "oxmjustworks.h"
30 #include "oxmrandompin.h"
31 #include "securevirtualresourcetypes.h"
32 #include "srmutility.h"
42 #define TAG "ClientOwnedBySubOwner"
45 static pthread_t oc_process_thread;
46 static bool g_LoopFlag = true;
48 static void* oc_process_loop(void* ptr)
50 struct timespec timeout;
52 timeout.tv_nsec = 100000000L;
57 nanosleep(&timeout, NULL);
59 pthread_join(&oc_process_thread, NULL);
63 static void StartOCProcessThread()
65 pthread_create(&oc_process_thread, NULL, oc_process_loop, NULL);
68 static void StopOCProcessThread()
73 // declaration(s) for provisioning client using C-level provisioning API
74 // user input definition for main loop on provisioning client
75 #define _10_DISCOV_OWN_DEVS_ 10
76 #define _20_GET_LED_RESOURCE_ 20
77 #define _21_PUT_LED_RESOURCE_ 21
78 #define _99_EXIT_PRVN_CLT_ 99
80 #define DISCOVERY_TIMEOUT 5 // 10 sec
81 #define CALLBACK_TIMEOUT 60 // 1 min
83 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client_owned_by_subowner.dat";
84 // '_' for separaing from the same constant variable in |srmresourcestrings.c|
85 static const char* PRVN_DB_FILE_NAME = "oic_prvn_cobs.db";
86 // |g_ctx| means provision manager application context and
87 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
88 // for accessing all function(s) for these, they are declared on global domain
89 static const char* g_ctx = "Provision Manager Client Application Context";
90 static char* g_svr_fname;
91 static char* g_prvn_fname;
92 static OCProvisionDev_t* g_own_list;
95 // function declaration(s) for calling them before implementing
96 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
97 static int printDevList(const OCProvisionDev_t*);
98 static size_t printUuidList(const OCUuidList_t*);
99 static int printResultList(const OCProvisionResult_t*, const int);
100 static void printUuid(const OicUuid_t*);
101 static FILE* fopen_prvnMng(const char*, const char*);
102 static int waitCallbackRet(void);
103 static int selectTwoDiffNum(int*, int*, const int, const char*);
105 // callback function(s) for provisioning client using C-level provisioning API
106 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
110 OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
114 OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
115 printResultList((const OCProvisionResult_t*) arr, nOfRes);
120 // response handler for LED requests.
121 static void LedCB(void *ctx, OCDoHandle UNUSED,
122 OCClientResponse *clientResponse)
126 if(clientResponse->result == OC_STACK_OK)
128 printf("Get OC_STACK_OK from server\n");
129 if(clientResponse->payload)
131 printf("Response ===================> %s\n", clientResponse->payload);
136 printf("Error in response : %d\n", clientResponse->result);
141 printf("Hit the response callback but can not find response data\n");
148 // function(s) for provisioning client using C-level provisioning API
149 static int initProvisionClient(void)
151 // initialize persistent storage for SVR DB
152 static OCPersistentStorage ps = {fopen_prvnMng, fread, fwrite, fclose, unlink};
153 if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&ps))
155 OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
159 // initialize OC stack and provisioning manager
160 if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
162 OIC_LOG(ERROR, TAG, "OCStack init error");
166 if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
168 printf("************************************************************\n");
169 printf("************Provisioning DB file already exists.************\n");
170 printf("************************************************************\n");
174 printf("*************************************************************\n");
175 printf("************No provisioning DB file, creating new************\n");
176 printf("*************************************************************\n");
179 if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
181 OIC_LOG(ERROR, TAG, "OC_PM init error");
188 static int discoverOwnedDevices(void)
190 // delete owned device list before updating it
193 OCDeleteDiscoveredDevices(g_own_list);
197 // call |OCDiscoverOwnedDevices| API actually
198 printf(" Discovering Only Owned Devices on Network..\n");
199 if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
201 OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
205 // display the discovered owned list
206 printf(" > Discovered Owned Devices\n");
207 g_own_cnt = printDevList(g_own_list);
212 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
214 if(!dev_lst || 0>=dev_num)
216 printf(" Device List is Empty..\n");
220 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
230 return NULL; // in here |lst| is always |NULL|
233 static int printDevList(const OCProvisionDev_t* dev_lst)
237 printf(" Device List is Empty..\n\n");
241 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
245 printf(" [%d] ", ++lst_cnt);
246 printUuid((const OicUuid_t*) &lst->doxm->deviceID);
255 static size_t printUuidList(const OCUuidList_t* uid_lst)
259 printf(" Device List is Empty..\n\n");
263 OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
267 printf(" [%zu] ", ++lst_cnt);
268 printUuid((const OicUuid_t*) &lst->dev);
277 static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
279 if(!rslt_lst || 0>=rslt_cnt)
281 printf(" Device List is Empty..\n\n");
286 for( ; rslt_cnt>lst_cnt; ++lst_cnt)
288 printf(" [%d] ", lst_cnt+1);
289 printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
290 printf(" - result: %d\n", rslt_lst[lst_cnt].res);
297 static void printUuid(const OicUuid_t* uid)
300 for(i=0; i<UUID_LENGTH; )
302 printf("%02X", (*uid).id[i++]);
303 if(i==4 || i==6 || i==8 || i==10) // canonical format for UUID has '8-4-4-4-12'
310 for(i = 0; i < UUID_LENGTH; i++)
312 printf("%c", (*uid).id[i]);
317 static FILE* fopen_prvnMng(const char* path, const char* mode)
319 (void)path; // unused |path| parameter
321 // input |g_svr_db_fname| internally by force, not using |path| parameter
322 // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
323 // with its own |SVR_DB_FILE_NAME|
324 return fopen(SVR_DB_FILE_NAME, mode);
327 static int waitCallbackRet(void)
329 for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
337 static void printMenu(void)
339 printf("************************************************************\n");
340 printf("****** OIC MOT Client with using C-level API ******\n");
341 printf("************************************************************\n\n");
343 printf("** [A] DISCOVER DEVICES ON NETWORK\n");
344 printf("** 10. Discover Owned Devices on Network\n\n");
346 printf("** [B] SEND GET/PUT Request\n");
347 printf("** 20. Send GET request\n");
348 printf("** 21. Send PUT request\n\n");
350 printf("** [G] EXIT PROVISIONING CLIENT\n");
351 printf("** 99. Exit Provisionong Client\n\n");
353 printf("************************************************************\n\n");
356 #if 0 // Code for enabling path configuration for PDB and SVR DBf
357 static void printUsage(void)
360 printf("OIC Provisioning Client with using C-level API\n");
361 printf("Usage: provisioningclient [option]...\n");
363 printf(" -h print help for this provisioning client\n");
364 printf(" -p=[prvn_db_file_path/name] input PRVN DB file path and name\n");
365 printf(" if not exists, will load default DB file\n");
366 printf(" (default: |oic_prvn_mng.db| on working dir)\n");
367 printf(" (ex. -p=oic_prvn_mng.db)\n");
368 printf(" -s=[svr_db_file_path/name] input SVR DB file path and name\n");
369 printf(" if not exists, will load default DB file\n");
370 printf(" (default: |oic_svr_db_client.json| on working dir)\n");
371 printf(" (ex. -s=oic_svr_db_client.json)\n");
376 // main function for provisioning client using C-level provisioning API
379 OCProvisionDev_t* selDev = NULL;
383 // initialize provisioning client
384 if(initProvisionClient())
386 OIC_LOG(ERROR, TAG, "ProvisionClient init error");
390 StartOCProcessThread();
391 printf("Client started...\n");
392 // main loop for provisioning manager
397 printf(">> Enter Menu Number: ");
398 for(int ret=0; 1!=ret; )
400 ret = scanf("%d", &mn_num);
401 for( ; 0x20<=getchar(); ); // for removing overflow garbages
402 // '0x20<=code' is character region
407 case _10_DISCOV_OWN_DEVS_:
408 if(discoverOwnedDevices())
410 OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
413 case _20_GET_LED_RESOURCE_:
415 char query[256] = {0};
416 OCCallbackData cbData;
418 cbData.context = NULL;
421 printDevList(g_own_list);
425 printf("Select the device : ");
426 for(int ret=0; 1!=ret; )
428 scanf(" %d", &selDevNum);
429 for( ; 0x20<=getchar(); ); // for removing overflow garbages
430 // '0x20<=code' is character region
432 if(0<selDevNum && g_own_cnt>=selDevNum)
436 printf(" Entered Wrong Number. Please Enter Again\n");
439 selDev = getDevInst(g_own_list, selDevNum);
442 OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
447 snprintf(query, MAX_URI_LENGTH, "coaps://%s:%d/a/led", selDev->endpoint.addr, selDev->securePort);
448 if(OC_STACK_OK != OCDoResource(NULL, OC_REST_GET, query, NULL, NULL, selDev->connType, OC_LOW_QOS, &cbData, NULL, 0))
450 printf("********************************\n");
451 printf("Failed to send GET request to %s\n", query);
452 printf("********************************\n");
461 case _21_PUT_LED_RESOURCE_:
463 char query[256] = {0};
464 OCCallbackData cbData;
466 cbData.context = NULL;
469 printDevList(g_own_list);
473 printf("Select the device : ");
474 for(int ret=0; 1!=ret; )
476 scanf(" %d", &selDevNum);
477 for( ; 0x20<=getchar(); ); // for removing overflow garbages
478 // '0x20<=code' is character region
480 if(0<selDevNum && g_own_cnt>=selDevNum)
484 printf(" Entered Wrong Number. Please Enter Again\n");
487 selDev = getDevInst(g_own_list, selDevNum);
490 OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
495 snprintf(query, MAX_URI_LENGTH, "coaps://%s:%d/a/led", selDev->endpoint.addr, selDev->securePort);
496 if(OC_STACK_OK != OCDoResource(NULL, OC_REST_PUT, query, NULL, NULL, selDev->connType, OC_LOW_QOS, &cbData, NULL, 0))
498 printf("********************************\n");
499 printf("Failed to send PUT request to %s\n", query);
500 printf("********************************\n");
509 case _99_EXIT_PRVN_CLT_:
512 printf(">> Entered Wrong Number. Please Enter Again\n\n");
518 if(OC_STACK_OK != OCStop())
520 OIC_LOG(ERROR, TAG, "OCStack stop error");
522 OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
526 OICFree(g_svr_fname); // after here |g_svr_fname| points nothing
530 OICFree(g_prvn_fname); // after here |g_prvn_fname| points nothing
533 StopOCProcessThread();
535 return 0; // always return normal case