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"
40 // declaration(s) for provisioning client using C-level provisioning API
41 // user input definition for main loop on provisioning client
42 #define _10_DISCOV_ALL_DEVS_ 10
43 #define _11_DISCOV_UNOWN_DEVS_ 11
44 #define _12_DISCOV_OWN_DEVS_ 12
45 #define _20_REGIST_DEVS_ 20
46 #define _30_PROVIS_PAIR_DEVS_ 30
47 #define _31_PROVIS_CRED_ 31
48 #define _32_PROVIS_ACL_ 32
49 #define _33_CHECK_LINK_STATUS_ 33
50 #define _40_UNLINK_PAIR_DEVS_ 40
51 #define _50_REMOVE_SELEC_DEV_ 50
52 #define _99_EXIT_PRVN_CLT_ 99
54 #define ACL_RESRC_MAX_NUM 16
55 #define ACL_RESRC_MAX_LEN 128
56 #define ACL_PEMISN_CNT 5
57 #define DISCOVERY_TIMEOUT 10 // 10 sec
58 #define CALLBACK_TIMEOUT 60 // 1 min
59 #define TAG "provisioningclient"
61 static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY"};
62 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.json";
63 // '_' for separaing from the same constant variable in |srmresourcestrings.c|
64 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
65 // |g_ctx| means provision manager application context and
66 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
67 // for accessing all function(s) for these, they are declared on global domain
68 static const char* g_ctx = "Provision Manager Client Application Context";
69 static char* g_svr_fname;
70 static char* g_prvn_fname;
71 static OCProvisionDev_t* g_own_list;
72 static OCProvisionDev_t* g_unown_list;
74 static int g_unown_cnt;
77 // function declaration(s) for calling them before implementing
78 static OicSecAcl_t* createAcl(const int);
79 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
80 static int printDevList(const OCProvisionDev_t*);
81 static size_t printUuidList(const OCUuidList_t*);
82 static int printResultList(const OCProvisionResult_t*, const int);
83 static void printUuid(const OicUuid_t*);
84 static FILE* fopen_prvnMng(const char*, const char*);
85 static int waitCallbackRet(void);
86 static int selectTwoDiffNum(int*, int*, const int, const char*);
88 // callback function(s) for provisioning client using C-level provisioning API
89 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
93 OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
97 OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
98 printResultList((const OCProvisionResult_t*) arr, nOfRes);
103 static void provisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
107 OIC_LOG_V(INFO, TAG, "Provision Pairwise SUCCEEDED - ctx: %s", (char*) ctx);
111 OIC_LOG_V(ERROR, TAG, "Provision Pairwise FAILED - ctx: %s", (char*) ctx);
112 printResultList((const OCProvisionResult_t*) arr, nOfRes);
117 static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
121 OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
125 OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
126 printResultList((const OCProvisionResult_t*) arr, nOfRes);
131 static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
135 OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
139 OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
140 printResultList((const OCProvisionResult_t*) arr, nOfRes);
145 static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
149 OIC_LOG_V(INFO, TAG, "Unlink Devices SUCCEEDED - ctx: %s", (char*) ctx);
153 OIC_LOG_V(ERROR, TAG, "Unlink Devices FAILED - ctx: %s", (char*) ctx);
154 printResultList((const OCProvisionResult_t*) arr, nOfRes);
159 static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
163 OIC_LOG_V(INFO, TAG, "Remove Device SUCCEEDED - ctx: %s", (char*) ctx);
167 OIC_LOG_V(ERROR, TAG, "Remove Device FAILED - ctx: %s", (char*) ctx);
168 printResultList((const OCProvisionResult_t*) arr, nOfRes);
173 static void inputPinCB(char* pin, size_t len)
175 if(!pin || OXM_RANDOM_PIN_SIZE>=len)
177 OIC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
181 printf(" > INPUT PIN: ");
182 for(int ret=0; 1!=ret; )
184 ret = scanf("%8s", pin);
185 for( ; 0x20<=getchar(); ); // for removing overflow garbages
186 // '0x20<=code' is character region
190 // function(s) for provisioning client using C-level provisioning API
191 static int initProvisionClient(void)
193 // initialize persistent storage for SVR DB
194 static OCPersistentStorage pstStr =
196 .open = fopen_prvnMng,
202 if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
204 OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
208 // initialize OC stack and provisioning manager
209 if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
211 OIC_LOG(ERROR, TAG, "OCStack init error");
215 if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
217 printf("************************************************************\n");
218 printf("************Provisioning DB file already exists.************\n");
219 printf("************************************************************\n");
223 printf("*************************************************************\n");
224 printf("************No provisioning DB file, creating new************\n");
225 printf("*************************************************************\n");
228 if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
230 OIC_LOG(ERROR, TAG, "OC_PM init error");
234 // register callback function(s) to each OxM
235 OTMCallbackData_t otmcb =
237 .loadSecretCB = LoadSecretJustWorksCallback,
238 .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
239 .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
240 .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
242 if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
244 OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
247 otmcb.loadSecretCB = InputPinCodeCallback;
248 otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
249 otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
250 otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
251 if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
253 OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
256 SetInputPinCB(inputPinCB);
261 static int discoverAllDevices(void)
263 // delete un/owned device lists before updating them
266 OCDeleteDiscoveredDevices(g_own_list);
271 OCDeleteDiscoveredDevices(g_unown_list);
275 // call |OCGetDevInfoFromNetwork| API actually
276 printf(" Discovering All Un/Owned Devices on Network..\n");
277 if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
279 OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
283 // display the discovered un/owned lists
284 printf(" > Discovered Owned Devices\n");
285 g_own_cnt = printDevList(g_own_list);
286 printf(" > Discovered Unowned Devices\n");
287 g_unown_cnt = printDevList(g_unown_list);
293 static int discoverUnownedDevices(void)
295 // delete unowned device list before updating it
298 OCDeleteDiscoveredDevices(g_unown_list);
302 // call |OCDiscoverUnownedDevices| API actually
303 printf(" Discovering Only Unowned Devices on Network..\n");
304 if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
306 OIC_LOG(ERROR, TAG, "OCDiscoverUnownedDevices API error");
310 // display the discovered unowned list
311 printf(" > Discovered Unowned Devices\n");
312 g_unown_cnt = printDevList(g_unown_list);
317 static int discoverOwnedDevices(void)
319 // delete owned device list before updating it
322 OCDeleteDiscoveredDevices(g_own_list);
326 // call |OCDiscoverOwnedDevices| API actually
327 printf(" Discovering Only Owned Devices on Network..\n");
328 if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
330 OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
334 // display the discovered owned list
335 printf(" > Discovered Owned Devices\n");
336 g_own_cnt = printDevList(g_own_list);
341 static int registerDevices(void)
343 // check |unown_list| for registering devices
344 if(!g_unown_list || 0>=g_unown_cnt)
346 printf(" > Unowned Device List, to Register Devices, is Empty\n");
347 printf(" > Please Discover Unowned Devices first, with [10|11] Menu\n");
348 return 0; // normal case
351 // call |OCDoOwnershipTransfer| API actually
352 // calling this API with callback actually acts like blocking
353 // for error checking, the return value saved and printed
355 printf(" Registering All Discovered Unowned Devices..\n");
356 OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
357 if(OC_STACK_OK != rst)
359 OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
362 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
364 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
368 // display the registered result
369 printf(" > Registered Discovered Unowned Devices\n");
370 printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
375 static int provisionPairwise(void)
377 // check |own_list| for provisioning pairwise devices
378 if(!g_own_list || 2>g_own_cnt)
380 printf(" > Owned Device List, to Provision the Pairwise, is Empty\n");
381 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
382 return 0; // normal case
385 // select two devices for provisioning pairwise devices
386 int dev_num[2] = {0};
387 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking Devices"))
389 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
390 return -1; // not need to 'goto' |ERROR| before allocating |acl|
393 // create ACL(s) for each selected device
394 OicSecAcl_t* acl[2] = {0};
395 for(int i=0; 2>i; ++i)
397 acl[i] = createAcl(dev_num[i]);
400 OIC_LOG(ERROR, TAG, "createAcl error return");
405 // call |OCProvisionPairwiseDevices| API actually
406 // calling this API with callback actually acts like blocking
407 // for error checking, the return value saved and printed
409 printf(" Provisioning Selected Pairwise Devices..\n");
411 OCProvisionPairwiseDevices((void*) g_ctx,
412 SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
413 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]), acl[0],
414 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]), acl[1],
415 provisionPairwiseCB);
416 if(OC_STACK_OK != rst)
418 OIC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
421 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
423 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
426 OCDeleteACLList(acl[0]);
427 OCDeleteACLList(acl[1]);
429 // display the pairwise-provisioned result
430 printf(" > Provisioned Selected Pairwise Devices\n");
431 printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
436 OCDeleteACLList(acl[0]);
437 OCDeleteACLList(acl[1]);
441 static int provisionCred(void)
443 // check |own_list| for provisioning pairwise credentials
444 if(!g_own_list || 2>g_own_cnt)
446 printf(" > Owned Device List, to Provision Credentials, is Empty\n");
447 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
448 return 0; // normal case
451 // select two devices for provisioning pairwise credentials
452 int dev_num[2] = {0};
453 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking CRED(s)"))
455 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
459 printf(" Select PSK length..\n");
460 printf(" 1 - 128bit(Default)\n");
461 printf(" 2 - 256bit\n");
464 for(int ret=0; 1!=ret; )
466 ret = scanf("%d",&sizeOption);
467 for( ; 0x20<=getchar(); ); // for removing overflow garbages
468 // '0x20<=code' is character region
476 size = OWNER_PSK_LENGTH_128;
481 size = OWNER_PSK_LENGTH_256;
486 size = OWNER_PSK_LENGTH_128;
492 // call |OCProvisionCredentials| API actually
493 // calling this API with callback actually acts like blocking
494 // for error checking, the return value saved and printed
496 printf(" Provisioning Selected Pairwise Credentials..\n");
498 OCProvisionCredentials((void*) g_ctx,
499 SYMMETRIC_PAIR_WISE_KEY, size,
500 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
501 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
503 if(OC_STACK_OK != rst)
505 OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
508 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
510 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
514 // display the CRED-provisioned result
515 printf(" > Provisioned Selected Pairwise Crendentials\n");
516 printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
521 static int provisionAcl(void)
523 // check |own_list| for provisioning access control list
524 if(!g_own_list || 1>g_own_cnt)
526 printf(" > Owned Device List, to Provision ACL, is Empty\n");
527 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
528 return 0; // normal case
531 // select device for provisioning access control list
535 printf(" > Enter Device Number, for Provisioning ACL: ");
536 for(int ret=0; 1!=ret; )
538 ret = scanf("%d", &dev_num);
539 for( ; 0x20<=getchar(); ); // for removing overflow garbages
540 // '0x20<=code' is character region
542 if(0<dev_num && g_own_cnt>=dev_num)
546 printf(" Entered Wrong Number. Please Enter Again\n");
549 // create ACL for selected device
550 OicSecAcl_t* acl = NULL;
551 acl = createAcl(dev_num);
554 OIC_LOG(ERROR, TAG, "createAcl error return");
558 // call |OCProvisionACL| API actually
559 // calling this API with callback actually acts like blocking
560 // for error checking, the return value saved and printed
562 printf(" Provisioning Selected ACL..\n");
563 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
566 OIC_LOG(ERROR, TAG, "provisionAcl: device instance empty");
569 OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
570 if(OC_STACK_OK != rst)
572 OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
575 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
577 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
580 OCDeleteACLList(acl); // after here |acl| points nothing
582 // display the ACL-provisioned result
583 printf(" > Provisioned Selected ACL\n");
588 OCDeleteACLList(acl); // after here |acl| points nothing
592 static int checkLinkedStatus(void)
594 // check |own_list| for checking selected link status on PRVN DB
595 if(!g_own_list || 1>g_own_cnt)
597 printf(" > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
598 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
599 return 0; // normal case
602 // select device for checking selected link status on PRVN DB
606 printf(" > Enter Device Number, for Checking Linked Status on PRVN DB: ");
607 for(int ret=0; 1!=ret; )
609 ret = scanf("%d", &dev_num);
610 for( ; 0x20<=getchar(); ); // for removing overflow garbages
611 // '0x20<=code' is character region
613 if(0<dev_num && g_own_cnt>=dev_num)
617 printf(" Entered Wrong Number. Please Enter Again\n");
620 // call |OCGetLinkedStatus| API actually
621 printf(" Checking Selected Link Status on PRVN DB..\n");
622 OCUuidList_t* dvid_lst = NULL;
624 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
625 if(!dev || !dev->doxm)
627 OIC_LOG(ERROR, TAG, "checkLinkedStatus: device instance empty");
633 &dev->doxm->deviceID,
634 &dvid_lst, &dvid_cnt)) // allow empty list
636 OIC_LOG(ERROR, TAG, "OCGetLinkedStatus API error");
640 // display the linked status result
641 printf(" > Checked Selected Link Status on PRVN DB\n");
642 if(!dvid_lst || !dvid_cnt) // |size_t| is unsigned
644 printf(" Linked Device List is Empty..\n");
645 return 0; // normal case
647 if(dvid_cnt != printUuidList((const OCUuidList_t*) dvid_lst))
649 OIC_LOG(ERROR, TAG, "printUuidList error return");
652 OCDeleteUuidList(dvid_lst);
657 OCDeleteUuidList(dvid_lst);
661 static int unlinkPairwise(void)
663 // check |own_list| for unlinking pairwise devices
664 if(!g_own_list || 2>g_own_cnt)
666 printf(" > Owned Device List, to Unlink the Pairwise, is Empty\n");
667 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
668 return 0; // normal case
671 // select two devices for unlinking pairwise devices
672 int dev_num[2] = {0};
673 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Unlinking Devices"))
675 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
679 // call |OCUnlinkDevices| API actually
680 // calling this API with callback actually acts like blocking
681 // for error checking, the return value saved and printed
683 printf(" Unlinking Selected Pairwise Devices..\n");
685 OCUnlinkDevices((void*) g_ctx,
686 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
687 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
689 if(OC_STACK_OK != rst)
691 OIC_LOG_V(ERROR, TAG, "OCUnlinkDevices API error: %d", rst);
694 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
696 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
700 // display the pairwise-unlinked result
701 printf(" > Unlinked Selected Pairwise Devices\n");
702 printf(" > Please Check Device's Status for the Unlinked Result, with [33] Menu\n");
707 static int removeDevice(void)
709 // check |own_list| for removing device
710 if(!g_own_list || 1>g_own_cnt)
712 printf(" > Owned Device List, to Remove Device, is Empty\n");
713 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
714 return 0; // normal case
717 // select device for removing it
721 printf(" > Enter Device Number, for Removing Device: ");
722 for(int ret=0; 1!=ret; )
724 ret = scanf("%d", &dev_num);
725 for( ; 0x20<=getchar(); ); // for removing overflow garbages
726 // '0x20<=code' is character region
728 if(0<dev_num && g_own_cnt>=dev_num)
732 printf(" Entered Wrong Number. Please Enter Again\n");
735 // call |OCRemoveDevice| API actually
736 // calling this API with callback actually acts like blocking
737 // for error checking, the return value saved and printed
739 printf(" Removing Selected Owned Device..\n");
741 OCRemoveDevice((void*) g_ctx, DISCOVERY_TIMEOUT,
742 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num), removeDeviceCB);
743 if(OC_STACK_OK != rst)
745 OIC_LOG_V(ERROR, TAG, "OCRemoveDevice API error: %d", rst);
748 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
750 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
754 // display the removed result
755 printf(" > Removed Selected Owned Device\n");
756 printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
761 static OicSecAcl_t* createAcl(const int dev_num)
763 if(0>=dev_num || g_own_cnt<dev_num)
765 OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
766 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
769 // allocate memory for |acl| struct
770 printf(" **** Create ACL for the Selected Device[%d]\n", dev_num);
771 OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
774 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
775 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
778 // enter |subject| device number
782 printf(" > [A] Enter Subject Device Number: ");
783 for(int ret=0; 1!=ret; )
785 ret = scanf("%d", &num);
786 for( ; 0x20<=getchar(); ); // for removing overflow garbages
787 // '0x20<=code' is character region
789 if(0<num && g_own_cnt>=num && dev_num!=num)
793 printf(" Entered Wrong Number. Please Enter Again\n");
796 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, num);
797 if(!dev || !dev->doxm)
799 OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
802 memcpy(&acl->subject, &dev->doxm->deviceID, UUID_LENGTH);
804 // enter number of |resources| in 'accessed' device
807 printf(" > [B] Enter Number of Accessed Resources (under 16): ");
808 // '16' is |ACL_RESRC_MAX_NUM|
809 for(int ret=0; 1!=ret; )
811 ret = scanf("%d", &num);
812 for( ; 0x20<=getchar(); ); // for removing overflow garbages
813 // '0x20<=code' is character region
815 if(0<num && ACL_RESRC_MAX_NUM>=num)
819 printf(" Entered Wrong Number. Please Enter under 16 Again\n");
820 // '16' is |ACL_RESRC_MAX_NUM|
823 // enter actually each 'accessed' |resources| name
824 printf(" Enter Each Accessed Resource Name (each under 128 char)\n");
825 // '128' is ACL_RESRC_MAX_LEN
826 acl->resourcesLen = (unsigned) num;
827 acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
830 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
833 char rsrc_in[ACL_RESRC_MAX_LEN+1] = {0}; // '1' for null termination
834 for(int i=0; acl->resourcesLen>(unsigned)i; ++i)
836 printf(" Enter Accessed Resource[%d] Name: ", i+1);
837 for(int ret=0; 1!=ret; )
839 ret = scanf("%128s", rsrc_in); // '128' is ACL_RESRC_MAX_LEN
840 for( ; 0x20<=getchar(); ); // for removing overflow garbages
841 // '0x20<=code' is character region
843 size_t len = strlen(rsrc_in)+1; // '1' for null termination
844 char* rsrc = (char*) OICCalloc(len, sizeof(char));
847 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
850 OICStrcpy(rsrc, len, rsrc_in);
851 acl->resources[i] = rsrc; // after here, |rsrc| points nothing
854 // enter |permission| for this access
855 printf(" > [C] Enter Permission for This Access\n");
856 uint16_t pmsn = PERMISSION_FULL_CONTROL; // default full permission
857 uint16_t pmsn_msk = PERMISSION_CREATE; // default permission mask
858 for(int i=0; ACL_PEMISN_CNT>i; ++i)
863 printf(" Enter %s Permission (y/n): ", ACL_PEMISN[i]);
864 for(int ret=0; 1!=ret; )
866 ret = scanf("%c", &ans);
867 for( ; 0x20<=getchar(); ); // for removing overflow garbages
868 // '0x20<=code' is character region
870 if('y'==ans || 'Y'==ans || 'n'==ans|| 'N'==ans)
872 ans &= ~0x20; // for masking lower case, 'y/n'
875 printf(" Entered Wrong Answer. Please Enter 'y/n' Again\n");
877 if('N' == ans) // masked lower case, 'n'
883 acl->permission = pmsn;
885 // enter |owner| device number
889 printf(" > [D] Enter Owner Device Number: ");
890 for(int ret=0; 1!=ret; )
892 ret = scanf("%d", &own_num);
893 for( ; 0x20<=getchar(); ); // for removing overflow garbages
894 // '0x20<=code' is character region
896 if(0<own_num && g_own_cnt>=own_num)
900 printf(" Entered Wrong Number. Please Enter Again\n");
903 acl->owners = (OicUuid_t*) OICCalloc(1, sizeof(OicUuid_t));
906 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
910 dev = getDevInst((const OCProvisionDev_t*)g_own_list, own_num);
911 if(!dev || !dev->doxm)
913 OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
916 memcpy(acl->owners, &dev->doxm->deviceID, UUID_LENGTH);
922 OCDeleteACLList(acl); // after here |acl| points nothing
926 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
928 if(!dev_lst || 0>=dev_num)
930 printf(" Device List is Empty..\n");
934 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
944 return NULL; // in here |lst| is always |NULL|
947 static int printDevList(const OCProvisionDev_t* dev_lst)
951 printf(" Device List is Empty..\n\n");
955 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
959 printf(" [%d] ", ++lst_cnt);
960 printUuid((const OicUuid_t*) &lst->doxm->deviceID);
969 static size_t printUuidList(const OCUuidList_t* uid_lst)
973 printf(" Device List is Empty..\n\n");
977 OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
981 printf(" [%zu] ", ++lst_cnt);
982 printUuid((const OicUuid_t*) &lst->dev);
991 static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
993 if(!rslt_lst || 0>=rslt_cnt)
995 printf(" Device List is Empty..\n\n");
1000 for( ; rslt_cnt>lst_cnt; ++lst_cnt)
1002 printf(" [%d] ", lst_cnt+1);
1003 printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
1004 printf(" - result: %d\n", rslt_lst[lst_cnt].res);
1011 static void printUuid(const OicUuid_t* uid)
1013 for(int i=0; i<UUID_LENGTH; )
1015 printf("%02X", (*uid).id[i++]);
1016 if(i==4 || i==6 || i==8 || i==10) // canonical format for UUID has '8-4-4-4-12'
1023 static FILE* fopen_prvnMng(const char* path, const char* mode)
1025 (void)path; // unused |path| parameter
1027 // input |g_svr_db_fname| internally by force, not using |path| parameter
1028 // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
1029 // with its own |SVR_DB_FILE_NAME|
1030 return fopen(SVR_DB_FILE_NAME, mode);
1033 static int waitCallbackRet(void)
1035 for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
1038 if(OC_STACK_OK != OCProcess())
1040 OIC_LOG(ERROR, TAG, "OCStack process error");
1048 static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
1050 if(!a || !b || 2>=max || !str)
1057 for(int i=0; 2>i; ++i)
1059 int* num = 0==i?a:b;
1062 printf(" > Enter Device[%d] Number, %s: ", i+1, str);
1063 for(int ret=0; 1!=ret; )
1065 ret = scanf("%d", num);
1066 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1067 // '0x20<=code' is character region
1069 if(0<*num && max>=*num)
1073 printf(" Entered Wrong Number. Please Enter Again\n");
1086 static void printMenu(void)
1088 printf("************************************************************\n");
1089 printf("****** OIC Provisioning Client with using C-level API ******\n");
1090 printf("************************************************************\n\n");
1092 printf("** [A] DISCOVER DEVICES ON NETWORK\n");
1093 printf("** 10. Discover All Un/Owned Devices on Network\n");
1094 printf("** 11. Discover Only Unowned Devices on Network\n");
1095 printf("** 12. Discover Only Owned Devices on Network\n\n");
1097 printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
1098 printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
1100 printf("** [C] PROVISION/LINK PAIRWISE THINGS\n");
1101 printf("** 30. Provision/Link Pairwise Things\n");
1102 printf("** 31. Provision Credentials for Pairwise Things\n");
1103 printf("** 32. Provision the Selected Access Control List(ACL)\n");
1104 printf("** 33. Check Linked Status of the Selected Device on PRVN DB\n\n");
1106 printf("** [D] UNLINK PAIRWISE THINGS\n");
1107 printf("** 40. Unlink Pairwise Things\n\n");
1109 printf("** [E] REMOVE THE SELECTED DEVICE\n");
1110 printf("** 50. Remove the Selected Device\n\n");
1112 printf("** [F] EXIT PROVISIONING CLIENT\n");
1113 printf("** 99. Exit Provisionong Client\n\n");
1115 printf("************************************************************\n\n");
1118 #if 0 // Code for enabling path configuration for PDB and SVR DBf
1119 static void printUsage(void)
1122 printf("OIC Provisioning Client with using C-level API\n");
1123 printf("Usage: provisioningclient [option]...\n");
1125 printf(" -h print help for this provisioning client\n");
1126 printf(" -p=[prvn_db_file_path/name] input PRVN DB file path and name\n");
1127 printf(" if not exists, will load default DB file\n");
1128 printf(" (default: |oic_prvn_mng.db| on working dir)\n");
1129 printf(" (ex. -p=oic_prvn_mng.db)\n");
1130 printf(" -s=[svr_db_file_path/name] input SVR DB file path and name\n");
1131 printf(" if not exists, will load default DB file\n");
1132 printf(" (default: |oic_svr_db_client.json| on working dir)\n");
1133 printf(" (ex. -s=oic_svr_db_client.json)\n");
1138 // main function for provisioning client using C-level provisioning API
1141 // initialize provisioning client
1142 if(initProvisionClient())
1144 OIC_LOG(ERROR, TAG, "ProvisionClient init error");
1148 // main loop for provisioning manager
1154 printf(">> Enter Menu Number: ");
1155 for(int ret=0; 1!=ret; )
1157 ret = scanf("%d", &mn_num);
1158 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1159 // '0x20<=code' is character region
1164 case _10_DISCOV_ALL_DEVS_:
1165 if(discoverAllDevices())
1167 OIC_LOG(ERROR, TAG, "_10_DISCOV_ALL_DEVS_: error");
1170 case _11_DISCOV_UNOWN_DEVS_:
1171 if(discoverUnownedDevices())
1173 OIC_LOG(ERROR, TAG, "_11_DISCOV_UNOWN_DEVS_: error");
1176 case _12_DISCOV_OWN_DEVS_:
1177 if(discoverOwnedDevices())
1179 OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
1182 case _20_REGIST_DEVS_:
1183 if(registerDevices())
1185 OIC_LOG(ERROR, TAG, "_20_REGIST_DEVS_: error");
1188 case _30_PROVIS_PAIR_DEVS_:
1189 if(provisionPairwise())
1191 OIC_LOG(ERROR, TAG, "_30_PROVIS_PAIR_DEVS_: error");
1194 case _31_PROVIS_CRED_:
1197 OIC_LOG(ERROR, TAG, "_31_PROVIS_CRED_: error");
1200 case _32_PROVIS_ACL_:
1203 OIC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
1206 case _33_CHECK_LINK_STATUS_:
1207 if(checkLinkedStatus())
1209 OIC_LOG(ERROR, TAG, "_33_CHECK_LINK_STATUS_: error");
1212 case _40_UNLINK_PAIR_DEVS_:
1213 if(unlinkPairwise())
1215 OIC_LOG(ERROR, TAG, "_40_UNLINK_PAIR_DEVS_: error");
1218 case _50_REMOVE_SELEC_DEV_:
1221 OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
1224 case _99_EXIT_PRVN_CLT_:
1227 printf(">> Entered Wrong Number. Please Enter Again\n\n");
1233 if(OC_STACK_OK != OCStop())
1235 OIC_LOG(ERROR, TAG, "OCStack stop error");
1237 OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
1238 OCDeleteDiscoveredDevices(g_unown_list); // after here |g_unown_list| points nothing
1242 OICFree(g_svr_fname); // after here |g_svr_fname| points nothing
1246 OICFree(g_prvn_fname); // after here |g_prvn_fname| points nothing
1248 return 0; // always return normal case
1253 #endif //__cplusplus