Merge branch 'windows-port'
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / sample / provisioningclient.c
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  *****************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26
27 #include "platform_features.h"
28 #include "logger.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31 #include "ocprovisioningmanager.h"
32 #include "oxmjustworks.h"
33 #include "oxmrandompin.h"
34 #include "securevirtualresourcetypes.h"
35 #include "srmutility.h"
36 #include "pmtypes.h"
37
38 #ifdef __cplusplus
39 extern "C"
40 {
41 #endif //__cplusplus
42
43 // declaration(s) for provisioning client using C-level provisioning API
44 // user input definition for main loop on provisioning client
45 #define _10_DISCOV_ALL_DEVS_    10
46 #define _11_DISCOV_UNOWN_DEVS_  11
47 #define _12_DISCOV_OWN_DEVS_    12
48 #define _20_REGIST_DEVS_        20
49 #define _30_PROVIS_PAIR_DEVS_   30
50 #define _31_PROVIS_CRED_        31
51 #define _32_PROVIS_ACL_         32
52 #define _33_PROVIS_DP_           33
53 #define _34_CHECK_LINK_STATUS_  34
54 #define _40_UNLINK_PAIR_DEVS_   40
55 #define _50_REMOVE_SELEC_DEV_   50
56 #define _60_GET_CRED_  60
57 #define _61_GET_ACL_            61
58 #define _99_EXIT_PRVN_CLT_      99
59
60 #define ACL_RESRC_MAX_NUM   16
61 #define ACL_RESRC_MAX_LEN   128
62 #define ACL_PEMISN_CNT      5
63 #define DISCOVERY_TIMEOUT   10  // 10 sec
64 #define CALLBACK_TIMEOUT    60  // 1 min
65 #define TAG "provisioningclient"
66
67 static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY"};
68 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.dat";
69         // '_' for separaing from the same constant variable in |srmresourcestrings.c|
70 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
71 static const OicSecPrm_t  SUPPORTED_PRMS[1] =
72 {
73     PRM_PRE_CONFIGURED,
74 };
75
76 // |g_ctx| means provision manager application context and
77 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
78 // for accessing all function(s) for these, they are declared on global domain
79 static const char* g_ctx = "Provision Manager Client Application Context";
80 static char* g_svr_fname;
81 static char* g_prvn_fname;
82 static OCProvisionDev_t* g_own_list;
83 static OCProvisionDev_t* g_unown_list;
84 static int g_own_cnt;
85 static int g_unown_cnt;
86 static bool g_doneCB;
87
88 // function declaration(s) for calling them before implementing
89 static OicSecAcl_t* createAcl(const int);
90 static OicSecPdAcl_t* createPdAcl(const int);
91 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
92 static int printDevList(const OCProvisionDev_t*);
93 static size_t printUuidList(const OCUuidList_t*);
94 static int printResultList(const OCProvisionResult_t*, const int);
95 static void printUuid(const OicUuid_t*);
96 static FILE* fopen_prvnMng(const char*, const char*);
97 static int waitCallbackRet(void);
98 static int selectTwoDiffNum(int*, int*, const int, const char*);
99
100 // callback function(s) for provisioning client using C-level provisioning API
101 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
102 {
103     if(!hasError)
104     {
105         OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
106     }
107     else
108     {
109         OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
110         printResultList((const OCProvisionResult_t*) arr, nOfRes);
111     }
112     g_doneCB = true;
113 }
114
115 static void provisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
116 {
117     if(!hasError)
118     {
119         OIC_LOG_V(INFO, TAG, "Provision Pairwise SUCCEEDED - ctx: %s", (char*) ctx);
120     }
121     else
122     {
123         OIC_LOG_V(ERROR, TAG, "Provision Pairwise FAILED - ctx: %s", (char*) ctx);
124         printResultList((const OCProvisionResult_t*) arr, nOfRes);
125     }
126     g_doneCB = true;
127 }
128
129 static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
130 {
131     if(!hasError)
132     {
133         OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
134     }
135     else
136     {
137         OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
138         printResultList((const OCProvisionResult_t*) arr, nOfRes);
139     }
140     g_doneCB = true;
141 }
142
143 static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
144 {
145     if(!hasError)
146     {
147         OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
148     }
149     else
150     {
151         OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
152         printResultList((const OCProvisionResult_t*) arr, nOfRes);
153     }
154     g_doneCB = true;
155 }
156
157 static void getCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
158 {
159     if(!hasError)
160     {
161         OIC_LOG_V(INFO, TAG, "getCredCB SUCCEEDED - ctx: %s", (char*) ctx);
162     }
163     else
164     {
165         OIC_LOG_V(ERROR, TAG, "getCredCB FAILED - ctx: %s", (char*) ctx);
166         printResultList((const OCProvisionResult_t*) arr, nOfRes);
167     }
168     g_doneCB = true;
169 }
170
171 static void getAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
172 {
173     if(!hasError)
174     {
175         OIC_LOG_V(INFO, TAG, "getAclCB SUCCEEDED - ctx: %s", (char*) ctx);
176     }
177     else
178     {
179         OIC_LOG_V(ERROR, TAG, "getAclCB FAILED - ctx: %s", (char*) ctx);
180         printResultList((const OCProvisionResult_t*) arr, nOfRes);
181     }
182     g_doneCB = true;
183 }
184
185 static void provisionDPCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
186 {
187     if(!hasError)
188     {
189         OIC_LOG_V(INFO, TAG, "Provision Direct-Pairing SUCCEEDED - ctx: %s", (char*) ctx);
190     }
191     else
192     {
193         OIC_LOG_V(ERROR, TAG, "Provision Direct-Pairing FAILED - ctx: %s", (char*) ctx);
194         printResultList((const OCProvisionResult_t*) arr, nOfRes);
195     }
196     g_doneCB = true;
197 }
198
199 static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
200 {
201     if(!hasError)
202     {
203         OIC_LOG_V(INFO, TAG, "Unlink Devices SUCCEEDED - ctx: %s", (char*) ctx);
204     }
205     else
206     {
207         OIC_LOG_V(ERROR, TAG, "Unlink Devices FAILED - ctx: %s", (char*) ctx);
208         printResultList((const OCProvisionResult_t*) arr, nOfRes);
209     }
210     g_doneCB = true;
211 }
212
213 static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
214 {
215     if(!hasError)
216     {
217         OIC_LOG_V(INFO, TAG, "Remove Device SUCCEEDED - ctx: %s", (char*) ctx);
218     }
219     else
220     {
221         OIC_LOG_V(ERROR, TAG, "Remove Device FAILED - ctx: %s", (char*) ctx);
222         printResultList((const OCProvisionResult_t*) arr, nOfRes);
223     }
224     g_doneCB = true;
225 }
226
227 static void inputPinCB(char* pin, size_t len)
228 {
229     if(!pin || OXM_RANDOM_PIN_SIZE>=len)
230     {
231         OIC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
232         return;
233     }
234
235     printf("   > INPUT PIN: ");
236     for(int ret=0; 1!=ret; )
237     {
238         ret = scanf("%8s", pin);
239         for( ; 0x20<=getchar(); );  // for removing overflow garbages
240                                     // '0x20<=code' is character region
241     }
242 }
243
244 // function(s) for provisioning client using C-level provisioning API
245 static int initProvisionClient(void)
246 {
247     // initialize persistent storage for SVR DB
248     static OCPersistentStorage pstStr =
249     {
250         .open = fopen_prvnMng,
251         .read = fread,
252         .write = fwrite,
253         .close = fclose,
254         .unlink = unlink
255     };
256     if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
257     {
258         OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
259         return -1;
260     }
261
262     // initialize OC stack and provisioning manager
263     if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
264     {
265         OIC_LOG(ERROR, TAG, "OCStack init error");
266         return -1;
267     }
268
269     if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
270     {
271         printf("************************************************************\n");
272         printf("************Provisioning DB file already exists.************\n");
273         printf("************************************************************\n");
274     }
275     else
276     {
277         printf("*************************************************************\n");
278         printf("************No provisioning DB file, creating new************\n");
279         printf("*************************************************************\n");
280     }
281
282     if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
283     {
284         OIC_LOG(ERROR, TAG, "OC_PM init error");
285         return -1;
286     }
287
288     // register callback function(s) to each OxM
289     OTMCallbackData_t otmcb =
290     {
291         .loadSecretCB = LoadSecretJustWorksCallback,
292         .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
293         .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
294         .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
295     };
296     if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
297     {
298         OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
299         return -1;
300     }
301     otmcb.loadSecretCB = InputPinCodeCallback;
302     otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallback;
303     otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
304     otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
305     if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
306     {
307         OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
308         return -1;
309     }
310     SetInputPinCB(inputPinCB);
311
312     return 0;
313 }
314
315 static int discoverAllDevices(void)
316 {
317     // delete un/owned device lists before updating them
318     if(g_own_list)
319     {
320         OCDeleteDiscoveredDevices(g_own_list);
321         g_own_list = NULL;
322     }
323     if(g_unown_list)
324     {
325         OCDeleteDiscoveredDevices(g_unown_list);
326         g_unown_list = NULL;
327     }
328
329     // call |OCGetDevInfoFromNetwork| API actually
330     printf("   Discovering All Un/Owned Devices on Network..\n");
331     if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
332     {
333         OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
334         return -1;
335     }
336
337     // display the discovered un/owned lists
338     printf("   > Discovered Owned Devices\n");
339     g_own_cnt = printDevList(g_own_list);
340     printf("   > Discovered Unowned Devices\n");
341     g_unown_cnt = printDevList(g_unown_list);
342
343     return 0;
344 }
345
346
347 static int discoverUnownedDevices(void)
348 {
349     // delete unowned device list before updating it
350     if(g_unown_list)
351     {
352         OCDeleteDiscoveredDevices(g_unown_list);
353         g_unown_list = NULL;
354     }
355
356     // call |OCDiscoverUnownedDevices| API actually
357     printf("   Discovering Only Unowned Devices on Network..\n");
358     if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
359     {
360         OIC_LOG(ERROR, TAG, "OCDiscoverUnownedDevices API error");
361         return -1;
362     }
363
364     // display the discovered unowned list
365     printf("   > Discovered Unowned Devices\n");
366     g_unown_cnt = printDevList(g_unown_list);
367
368     return 0;
369 }
370
371 static int discoverOwnedDevices(void)
372 {
373     // delete owned device list before updating it
374     if(g_own_list)
375     {
376         OCDeleteDiscoveredDevices(g_own_list);
377         g_own_list = NULL;
378     }
379
380     // call |OCDiscoverOwnedDevices| API actually
381     printf("   Discovering Only Owned Devices on Network..\n");
382     if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
383     {
384         OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
385         return -1;
386     }
387
388     // display the discovered owned list
389     printf("   > Discovered Owned Devices\n");
390     g_own_cnt = printDevList(g_own_list);
391
392     return 0;
393 }
394
395 static int registerDevices(void)
396 {
397     // check |unown_list| for registering devices
398     if(!g_unown_list || 0>=g_unown_cnt)
399     {
400         printf("   > Unowned Device List, to Register Devices, is Empty\n");
401         printf("   > Please Discover Unowned Devices first, with [10|11] Menu\n");
402         return 0;  // normal case
403     }
404
405     // call |OCDoOwnershipTransfer| API actually
406     // calling this API with callback actually acts like blocking
407     // for error checking, the return value saved and printed
408     g_doneCB = false;
409     printf("   Registering All Discovered Unowned Devices..\n");
410     OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
411     if(OC_STACK_OK != rst)
412     {
413         OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
414         return -1;
415     }
416     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
417     {
418         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
419         return -1;
420     }
421
422     // display the registered result
423     printf("   > Registered Discovered Unowned Devices\n");
424     printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
425
426     return 0;
427 }
428
429 static int provisionPairwise(void)
430 {
431     // check |own_list| for provisioning pairwise devices
432     if(!g_own_list || 2>g_own_cnt)
433     {
434         printf("   > Owned Device List, to Provision the Pairwise, is Empty\n");
435         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
436         return 0;  // normal case
437     }
438
439     // select two devices for provisioning pairwise devices
440     int dev_num[2] = {0};
441     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking Devices"))
442     {
443         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
444         return -1;  // not need to 'goto' |ERROR| before allocating |acl|
445     }
446
447     // create ACL(s) for each selected device
448     OicSecAcl_t* acl[2] = {0};
449     for(int i=0; 2>i; ++i)
450     {
451         acl[i] = createAcl(dev_num[i]);
452         if(!acl[i])
453         {
454             OIC_LOG(ERROR, TAG, "createAcl error return");
455             goto PVPWS_ERROR;
456         }
457     }
458
459     // call |OCProvisionPairwiseDevices| API actually
460     // calling this API with callback actually acts like blocking
461     // for error checking, the return value saved and printed
462     g_doneCB = false;
463     printf("   Provisioning Selected Pairwise Devices..\n");
464     OCStackResult rst =
465             OCProvisionPairwiseDevices((void*) g_ctx,
466                     SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
467                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]), acl[0],
468                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]), acl[1],
469                     provisionPairwiseCB);
470     if(OC_STACK_OK != rst)
471     {
472         OIC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
473         goto PVPWS_ERROR;
474     }
475     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
476     {
477         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
478         goto PVPWS_ERROR;
479     }
480     OCDeleteACLList(acl[0]);
481     OCDeleteACLList(acl[1]);
482
483     // display the pairwise-provisioned result
484     printf("   > Provisioned Selected Pairwise Devices\n");
485     printf("   > Please Check Device's Status for the Linked Result, with [33] Menu\n");
486
487     return 0;
488
489 PVPWS_ERROR:
490     OCDeleteACLList(acl[0]);
491     OCDeleteACLList(acl[1]);
492     return -1;
493 }
494
495 static int provisionCred(void)
496 {
497     // check |own_list| for provisioning pairwise credentials
498     if(!g_own_list || 2>g_own_cnt)
499     {
500         printf("   > Owned Device List, to Provision Credentials, is Empty\n");
501         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
502         return 0;  // normal case
503     }
504
505     // select two devices for provisioning pairwise credentials
506     int dev_num[2] = {0};
507     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking CRED(s)"))
508     {
509         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
510         return -1;
511     }
512
513     printf("   Select PSK length..\n");
514     printf("   1 - 128bit(Default)\n");
515     printf("   2 - 256bit\n");
516     int sizeOption = 0;
517
518     for(int ret=0; 1!=ret; )
519     {
520          ret = scanf("%d",&sizeOption);
521          for( ; 0x20<=getchar(); );  // for removing overflow garbages
522                                     // '0x20<=code' is character region
523     }
524     size_t size = 0;
525
526     switch(sizeOption)
527     {
528         case 1:
529         {
530             size = OWNER_PSK_LENGTH_128;
531             break;
532         }
533         case 2:
534         {
535             size = OWNER_PSK_LENGTH_256;
536             break;
537         }
538         default:
539         {
540             size = OWNER_PSK_LENGTH_128;
541             break;
542         }
543     }
544
545
546     // call |OCProvisionCredentials| API actually
547     // calling this API with callback actually acts like blocking
548     // for error checking, the return value saved and printed
549     g_doneCB = false;
550     printf("   Provisioning Selected Pairwise Credentials..\n");
551     OCStackResult rst =
552             OCProvisionCredentials((void*) g_ctx,
553                     SYMMETRIC_PAIR_WISE_KEY, size,
554                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
555                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
556                     provisionCredCB);
557     if(OC_STACK_OK != rst)
558     {
559         OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
560         return -1;
561     }
562     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
563     {
564         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
565         return -1;
566     }
567
568     // display the CRED-provisioned result
569     printf("   > Provisioned Selected Pairwise Crendentials\n");
570     printf("   > Please Check Device's Status for the Linked Result, with [33] Menu\n");
571
572     return 0;
573 }
574
575 static int provisionAcl(void)
576 {
577     // check |own_list| for provisioning access control list
578     if(!g_own_list || 1>g_own_cnt)
579     {
580         printf("   > Owned Device List, to Provision ACL, is Empty\n");
581         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
582         return 0;  // normal case
583     }
584
585     // select device for provisioning access control list
586     int dev_num = 0;
587     for( ; ; )
588     {
589         printf("   > Enter Device Number, for Provisioning ACL: ");
590         for(int ret=0; 1!=ret; )
591         {
592             ret = scanf("%d", &dev_num);
593             for( ; 0x20<=getchar(); );  // for removing overflow garbages
594                                         // '0x20<=code' is character region
595         }
596         if(0<dev_num && g_own_cnt>=dev_num)
597         {
598             break;
599         }
600         printf("     Entered Wrong Number. Please Enter Again\n");
601     }
602
603     // create ACL for selected device
604     OicSecAcl_t* acl = NULL;
605     acl = createAcl(dev_num);
606     if(!acl)
607     {
608         OIC_LOG(ERROR, TAG, "createAcl error return");
609         goto PVACL_ERROR;
610     }
611
612     // call |OCProvisionACL| API actually
613     // calling this API with callback actually acts like blocking
614     // for error checking, the return value saved and printed
615     g_doneCB = false;
616     printf("   Provisioning Selected ACL..\n");
617     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
618     if(!dev)
619     {
620         OIC_LOG(ERROR, TAG, "provisionAcl: device instance empty");
621         goto PVACL_ERROR;
622     }
623     OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
624     if(OC_STACK_OK != rst)
625     {
626         OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
627         goto PVACL_ERROR;
628     }
629     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
630     {
631         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
632         goto PVACL_ERROR;
633     }
634     OCDeleteACLList(acl);  // after here |acl| points nothing
635
636     // display the ACL-provisioned result
637     printf("   > Provisioned Selected ACL\n");
638
639     return 0;
640
641 PVACL_ERROR:
642     OCDeleteACLList(acl);  // after here |acl| points nothing
643     return -1;
644 }
645
646 static int provisionDirectPairing(void)
647 {
648     // check |own_list| for provisioning direct-pairing
649     if(!g_own_list || 1>g_own_cnt)
650     {
651         printf("   > Owned Device List, to Provision ACL, is Empty\n");
652         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
653         return 0;  // normal case
654     }
655
656     // select device for provisioning direct-pairing
657     int dev_num = 0;
658     for( ; ; )
659     {
660         printf("   > Enter Device Number, for Provisioning Direct-Pairing: ");
661         for(int ret=0; 1!=ret; )
662         {
663             ret = scanf("%d", &dev_num);
664             for( ; 0x20<=getchar(); );  // for removing overflow garbages
665                                         // '0x20<=code' is character region
666         }
667         if(0<dev_num && g_own_cnt>=dev_num)
668         {
669             break;
670         }
671         printf("     Entered Wrong Number. Please Enter Again\n");
672     }
673
674     // create Direct-Pairing Configuration(PIN, PDACL) for selected device
675     // TODO: default acl -> input from user !
676     OicSecPconf_t pconf;
677     memset(&pconf, 0, sizeof(OicSecPconf_t));
678
679     // set enable dp
680     pconf.edp = true;
681
682     // set default supported PRM types
683     pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
684     pconf.prm = (OicSecPrm_t *)OICCalloc(pconf.prmLen, sizeof(OicSecPrm_t));
685     if(pconf.prm)
686     {
687         for (size_t i=0; i<pconf.prmLen; i++)
688         {
689             pconf.prm[i] = SUPPORTED_PRMS[i];
690         }
691     }
692     else
693     {
694         OIC_LOG(ERROR, TAG, "create prm error return");
695         goto PVDP_ERROR;
696     }
697
698     // set default pin
699     const char DP_DEFAULT_PIN[] = "00000000";
700     memcpy(pconf.pin.val, DP_DEFAULT_PIN, DP_PIN_LENGTH);
701
702     // set default pdacl
703     pconf.pdacls = createPdAcl(dev_num);
704     if(!pconf.pdacls)
705     {
706         OIC_LOG(ERROR, TAG, "createPdAcl error return");
707         goto PVDP_ERROR;
708     }
709
710     // call |OCProvisionDirectPairing| API actually
711     // calling this API with callback actually acts like blocking
712     // for error checking, the return value saved and printed
713     g_doneCB = false;
714     printf("   Atempt Direct-Pairing Provisioning (PIN : [%s])..\n", (char*)pconf.pin.val);
715     OCStackResult rst = OCProvisionDirectPairing((void*) g_ctx,
716                                        getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
717                                        &pconf, provisionDPCB);
718     if(OC_STACK_OK != rst)
719     {
720         OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
721         if (OC_STACK_UNAUTHORIZED_REQ == rst)
722         {
723             OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
724         }
725         goto PVDP_ERROR;
726     }
727     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
728     {
729         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
730         goto PVDP_ERROR;
731     }
732     OCDeletePdAclList(pconf.pdacls);
733
734     // display the PCONF-provisioned result
735     printf("   > SUCCESS to provision Direct-Pairing !!\n");
736
737     return 0;
738
739 PVDP_ERROR:
740     OCDeletePdAclList(pconf.pdacls);  // after here |acl| points nothing
741     return -1;
742 }
743
744 static int checkLinkedStatus(void)
745 {
746     // check |own_list| for checking selected link status on PRVN DB
747     if(!g_own_list || 1>g_own_cnt)
748     {
749         printf("   > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
750         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
751         return 0;  // normal case
752     }
753
754     // select device for checking selected link status on PRVN DB
755     int dev_num = 0;
756     for( ; ; )
757     {
758         printf("   > Enter Device Number, for Checking Linked Status on PRVN DB: ");
759         for(int ret=0; 1!=ret; )
760         {
761             ret = scanf("%d", &dev_num);
762             for( ; 0x20<=getchar(); );  // for removing overflow garbages
763                                         // '0x20<=code' is character region
764         }
765         if(0<dev_num && g_own_cnt>=dev_num)
766         {
767             break;
768         }
769         printf("     Entered Wrong Number. Please Enter Again\n");
770     }
771
772     // call |OCGetLinkedStatus| API actually
773     printf("   Checking Selected Link Status on PRVN DB..\n");
774     OCUuidList_t* dvid_lst = NULL;
775     size_t dvid_cnt = 0;
776     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
777     if(!dev || !dev->doxm)
778     {
779         OIC_LOG(ERROR, TAG, "checkLinkedStatus: device instance empty");
780         goto CKLST_ERROR;
781     }
782
783     if(OC_STACK_OK !=
784             OCGetLinkedStatus(
785                     &dev->doxm->deviceID,
786                     &dvid_lst, &dvid_cnt))  // allow empty list
787     {
788         OIC_LOG(ERROR, TAG, "OCGetLinkedStatus API error");
789         goto CKLST_ERROR;
790     }
791
792     // display the linked status result
793     printf("   > Checked Selected Link Status on PRVN DB\n");
794     if(!dvid_lst || !dvid_cnt)  // |size_t| is unsigned
795     {
796         printf("     Linked Device List is Empty..\n");
797         return 0;  // normal case
798     }
799     if(dvid_cnt != printUuidList((const OCUuidList_t*) dvid_lst))
800     {
801         OIC_LOG(ERROR, TAG, "printUuidList error return");
802         goto CKLST_ERROR;
803     }
804     OCDeleteUuidList(dvid_lst);
805
806     return 0;
807
808 CKLST_ERROR:
809     OCDeleteUuidList(dvid_lst);
810     return -1;
811 }
812
813 static int getCred(void)
814 {
815     // check |own_list| for checking selected link status on PRVN DB
816     if(!g_own_list || 1>g_own_cnt)
817     {
818         printf("   > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
819         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
820         return 0;  // normal case
821     }
822
823     // select device for checking selected link status on PRVN DB
824     int dev_num = 0;
825     for( ; ; )
826     {
827         printf("   > Enter Device Number, for Checking Linked Status on PRVN DB: ");
828         for(int ret=0; 1!=ret; )
829         {
830             ret = scanf("%d", &dev_num);
831             for( ; 0x20<=getchar(); );  // for removing overflow garbages
832                                         // '0x20<=code' is character region
833         }
834         if(0<dev_num && g_own_cnt>=dev_num)
835         {
836             break;
837         }
838         printf("     Entered Wrong Number. Please Enter Again\n");
839     }
840
841     // call |getDevInst| API actually
842     // calling this API with callback actually acts like blocking
843     // for error checking, the return value saved and printed
844     g_doneCB = false;
845     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
846     if(!dev)
847     {
848         OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
849         goto PVACL_ERROR;
850     }
851     OCStackResult rst = OCGetCredResource((void*) g_ctx, dev, getCredCB);
852     if(OC_STACK_OK != rst)
853     {
854         OIC_LOG_V(ERROR, TAG, "OCGetCred API error: %d", rst);
855         goto PVACL_ERROR;
856     }
857     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
858     {
859         OIC_LOG(ERROR, TAG, "OCGetCredResource callback error");
860         goto PVACL_ERROR;
861     }
862
863     // display the result of get credential
864     printf("   > Get Cred SUCCEEDED\n");
865
866     return 0;
867
868 PVACL_ERROR:
869     return -1;
870 }
871
872 static int getAcl(void)
873 {
874     // check |own_list| for checking selected link status on PRVN DB
875     if(!g_own_list || 1>g_own_cnt)
876     {
877         printf("   > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
878         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
879         return 0;  // normal case
880     }
881
882     // select device for checking selected link status on PRVN DB
883     int dev_num = 0;
884     for( ; ; )
885     {
886         printf("   > Enter Device Number, for Checking Linked Status on PRVN DB: ");
887         for(int ret=0; 1!=ret; )
888         {
889             ret = scanf("%d", &dev_num);
890             for( ; 0x20<=getchar(); );  // for removing overflow garbages
891                                         // '0x20<=code' is character region
892         }
893         if(0<dev_num && g_own_cnt>=dev_num)
894         {
895             break;
896         }
897         printf("     Entered Wrong Number. Please Enter Again\n");
898     }
899
900     // call |getDevInst| API actually
901     // calling this API with callback actually acts like blocking
902     // for error checking, the return value saved and printed
903     g_doneCB = false;
904     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
905     if(!dev)
906     {
907         OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
908         goto PVACL_ERROR;
909     }
910     OCStackResult rst = OCGetACLResource((void*) g_ctx, dev, getAclCB);
911     if(OC_STACK_OK != rst)
912     {
913         OIC_LOG_V(ERROR, TAG, "OCGetACLResource API error: %d", rst);
914
915         goto PVACL_ERROR;
916     }
917     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
918     {
919         OIC_LOG(ERROR, TAG, "OCGetACLResource callback error");
920         goto PVACL_ERROR;
921     }
922
923     // display the result of get credential
924     printf("   > Get ACL SUCCEEDED\n");
925
926     return 0;
927
928 PVACL_ERROR:
929     return -1;
930 }
931
932 static int unlinkPairwise(void)
933 {
934     // check |own_list| for unlinking pairwise devices
935     if(!g_own_list || 2>g_own_cnt)
936     {
937         printf("   > Owned Device List, to Unlink the Pairwise, is Empty\n");
938         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
939         return 0;  // normal case
940     }
941
942     // select two devices for unlinking pairwise devices
943     int dev_num[2] = {0};
944     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Unlinking Devices"))
945     {
946         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
947         return -1;
948     }
949
950     // call |OCUnlinkDevices| API actually
951     // calling this API with callback actually acts like blocking
952     // for error checking, the return value saved and printed
953     g_doneCB = false;
954     printf("   Unlinking Selected Pairwise Devices..\n");
955     OCStackResult rst =
956             OCUnlinkDevices((void*) g_ctx,
957                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
958                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
959                     unlinkDevicesCB);
960     if(OC_STACK_OK != rst)
961     {
962         OIC_LOG_V(ERROR, TAG, "OCUnlinkDevices API error: %d", rst);
963         return -1;
964     }
965     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
966     {
967         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
968         return -1;
969     }
970
971     // display the pairwise-unlinked result
972     printf("   > Unlinked Selected Pairwise Devices\n");
973     printf("   > Please Check Device's Status for the Unlinked Result, with [33] Menu\n");
974
975     return 0;
976 }
977
978 static int removeDevice(void)
979 {
980     // check |own_list| for removing device
981     if(!g_own_list || 1>g_own_cnt)
982     {
983         printf("   > Owned Device List, to Remove Device, is Empty\n");
984         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
985         return 0;  // normal case
986     }
987
988     // select device for removing it
989     int dev_num = 0;
990     for( ; ; )
991     {
992         printf("   > Enter Device Number, for Removing Device: ");
993         for(int ret=0; 1!=ret; )
994         {
995             ret = scanf("%d", &dev_num);
996             for( ; 0x20<=getchar(); );  // for removing overflow garbages
997                                         // '0x20<=code' is character region
998         }
999         if(0<dev_num && g_own_cnt>=dev_num)
1000         {
1001             break;
1002         }
1003         printf("     Entered Wrong Number. Please Enter Again\n");
1004     }
1005
1006     // call |OCRemoveDevice| API actually
1007     // calling this API with callback actually acts like blocking
1008     // for error checking, the return value saved and printed
1009     g_doneCB = false;
1010     printf("   Removing Selected Owned Device..\n");
1011     OCStackResult rst =
1012             OCRemoveDevice((void*) g_ctx, DISCOVERY_TIMEOUT,
1013                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num), removeDeviceCB);
1014     if(OC_STACK_OK != rst)
1015     {
1016         OIC_LOG_V(ERROR, TAG, "OCRemoveDevice API error: %d", rst);
1017         return -1;
1018     }
1019     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
1020     {
1021         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
1022         return -1;
1023     }
1024
1025     // display the removed result
1026     printf("   > Removed Selected Owned Device\n");
1027     printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
1028
1029     return 0;
1030 }
1031
1032 static OicSecAcl_t* createAcl(const int dev_num)
1033 {
1034     if(0>=dev_num || g_own_cnt<dev_num)
1035     {
1036         OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1037         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1038     }
1039
1040     // allocate memory for |acl| struct
1041     printf("   **** Create ACL for the Selected Device[%d]\n", dev_num);
1042     OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
1043     if(!acl)
1044     {
1045         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1046         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1047     }
1048
1049     // enter |subject| device number
1050     int num = 0;
1051     for( ; ; )
1052     {
1053         printf("   > [A] Enter Subject Device Number: ");
1054         for(int ret=0; 1!=ret; )
1055         {
1056             ret = scanf("%d", &num);
1057             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1058                                         // '0x20<=code' is character region
1059         }
1060         if(0<num && g_own_cnt>=num && dev_num!=num)
1061         {
1062             break;
1063         }
1064         printf("     Entered Wrong Number. Please Enter Again\n");
1065     }
1066
1067     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, num);
1068     if(!dev || !dev->doxm)
1069     {
1070         OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
1071         goto CRACL_ERROR;
1072     }
1073     memcpy(&acl->subject, &dev->doxm->deviceID, UUID_LENGTH);
1074
1075     // enter number of |resources| in 'accessed' device
1076     for( ; ; )
1077     {
1078         printf("   > [B] Enter Number of Accessed Resources (under 16): ");
1079                 // '16' is |ACL_RESRC_MAX_NUM|
1080         for(int ret=0; 1!=ret; )
1081         {
1082             ret = scanf("%d", &num);
1083             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1084                                         // '0x20<=code' is character region
1085         }
1086         if(0<num && ACL_RESRC_MAX_NUM>=num)
1087         {
1088             break;
1089         }
1090         printf("     Entered Wrong Number. Please Enter under 16 Again\n");
1091                 // '16' is |ACL_RESRC_MAX_NUM|
1092     }
1093
1094     // enter actually each 'accessed' |resources| name
1095     printf("         Enter Each Accessed Resource Name (each under 128 char)\n");
1096             // '128' is ACL_RESRC_MAX_LEN
1097     acl->resourcesLen = (unsigned) num;
1098     acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
1099     if(!acl->resources)
1100     {
1101         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1102         goto CRACL_ERROR;
1103     }
1104     char rsrc_in[ACL_RESRC_MAX_LEN+1] = {0};  // '1' for null termination
1105     for(int i=0; acl->resourcesLen>(unsigned)i; ++i)
1106     {
1107         printf("         Enter Accessed Resource[%d] Name: ", i+1);
1108         for(int ret=0; 1!=ret; )
1109         {
1110             ret = scanf("%128s", rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
1111             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1112                                         // '0x20<=code' is character region
1113         }
1114         size_t len = strlen(rsrc_in)+1;  // '1' for null termination
1115         char* rsrc = (char*) OICCalloc(len, sizeof(char));
1116         if(!rsrc)
1117         {
1118             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1119             goto CRACL_ERROR;
1120         }
1121         OICStrcpy(rsrc, len, rsrc_in);
1122         acl->resources[i] = rsrc;  // after here, |rsrc| points nothing
1123     }
1124
1125     // enter |permission| for this access
1126     printf("   > [C] Enter Permission for This Access\n");
1127     uint16_t pmsn = PERMISSION_FULL_CONTROL;  // default full permission
1128     uint16_t pmsn_msk = PERMISSION_CREATE;  // default permission mask
1129     for(int i=0; ACL_PEMISN_CNT>i; ++i)
1130     {
1131         char ans = 0;
1132         for( ; ; )
1133         {
1134             printf("         Enter %s Permission (y/n): ", ACL_PEMISN[i]);
1135             for(int ret=0; 1!=ret; )
1136             {
1137                 ret = scanf("%c", &ans);
1138                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
1139                                             // '0x20<=code' is character region
1140             }
1141             if('y'==ans || 'Y'==ans || 'n'==ans|| 'N'==ans)
1142             {
1143                 ans &= ~0x20;  // for masking lower case, 'y/n'
1144                 break;
1145             }
1146             printf("         Entered Wrong Answer. Please Enter 'y/n' Again\n");
1147         }
1148         if('N' == ans)  // masked lower case, 'n'
1149         {
1150             pmsn -= pmsn_msk;
1151         }
1152         pmsn_msk <<= 1;
1153     }
1154     acl->permission = pmsn;
1155
1156     // enter |owner| device number
1157     int own_num = 0;
1158     for( ; ; )
1159     {
1160         printf("   > [D] Enter Owner Device Number: ");
1161         for(int ret=0; 1!=ret; )
1162         {
1163             ret = scanf("%d", &own_num);
1164             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1165                                         // '0x20<=code' is character region
1166         }
1167         if(0<own_num && g_own_cnt>=own_num)
1168         {
1169             break;
1170         }
1171         printf("         Entered Wrong Number. Please Enter Again\n");
1172     }
1173
1174     dev = getDevInst((const OCProvisionDev_t*)g_own_list, own_num);
1175     if(!dev || !dev->doxm)
1176     {
1177         OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
1178         goto CRACL_ERROR;
1179     }
1180     memcpy(&acl->rownerID, &dev->doxm->deviceID, sizeof(OicUuid_t));
1181     printf("\n");
1182
1183     return acl;
1184
1185 CRACL_ERROR:
1186     OCDeleteACLList(acl);  // after here |acl| points nothing
1187     return NULL;
1188 }
1189
1190 static OicSecPdAcl_t* createPdAcl(const int dev_num)
1191 {
1192     if(0>=dev_num || g_own_cnt<dev_num)
1193     {
1194         OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1195         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1196     }
1197
1198     // allocate memory for |pdacl| struct
1199     printf("   **** Create PDACL for the Selected Device[%d]\n", dev_num);
1200     OicSecPdAcl_t* pdAcl = (OicSecPdAcl_t*) OICCalloc(1, sizeof(OicSecPdAcl_t));
1201     if(!pdAcl)
1202     {
1203         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1204         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1205     }
1206
1207
1208     // number of resources
1209     char rsrc_in[][ACL_RESRC_MAX_LEN+1] = {"*", "/rsrc/*"};
1210     pdAcl->resourcesLen = 1;
1211
1212     // resource
1213     int num = pdAcl->resourcesLen;
1214     pdAcl->resources = (char**) OICCalloc(num, sizeof(char*));
1215     if(!pdAcl->resources)
1216     {
1217         OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1218         goto CRPDACL_ERROR;
1219     }
1220     for(int i=0; num>i; ++i)
1221     {
1222         size_t len = strlen(rsrc_in[i])+1;  // '1' for null termination
1223         char* rsrc = (char*) OICCalloc(len, sizeof(char));
1224         if(!rsrc)
1225         {
1226             OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1227             goto CRPDACL_ERROR;
1228         }
1229         OICStrcpy(rsrc, len, rsrc_in[i]);
1230         pdAcl->resources[i] = rsrc;  // after here, |rsrc| points nothing
1231     }
1232
1233     // permission
1234     pdAcl->permission = PERMISSION_FULL_CONTROL;
1235
1236     return pdAcl;
1237
1238 CRPDACL_ERROR:
1239     OCDeletePdAclList(pdAcl);
1240     return NULL;
1241 }
1242
1243 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
1244 {
1245     if(!dev_lst || 0>=dev_num)
1246     {
1247         printf("     Device List is Empty..\n");
1248         return NULL;
1249     }
1250
1251     OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1252     for(int i=0; lst; )
1253     {
1254         if(dev_num == ++i)
1255         {
1256             return lst;
1257         }
1258         lst = lst->next;
1259     }
1260
1261     return NULL;  // in here |lst| is always |NULL|
1262 }
1263
1264 static int printDevList(const OCProvisionDev_t* dev_lst)
1265 {
1266     if(!dev_lst)
1267     {
1268         printf("     Device List is Empty..\n\n");
1269         return 0;
1270     }
1271
1272     OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1273     int lst_cnt = 0;
1274     for( ; lst; )
1275     {
1276         printf("     [%d] ", ++lst_cnt);
1277         printUuid((const OicUuid_t*) &lst->doxm->deviceID);
1278         printf("\n");
1279         lst = lst->next;
1280     }
1281     printf("\n");
1282
1283     return lst_cnt;
1284 }
1285
1286 static size_t printUuidList(const OCUuidList_t* uid_lst)
1287 {
1288     if(!uid_lst)
1289     {
1290         printf("     Device List is Empty..\n\n");
1291         return 0;
1292     }
1293
1294     OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
1295     size_t lst_cnt = 0;
1296     for( ; lst; )
1297     {
1298         printf("     [%zu] ", ++lst_cnt);
1299         printUuid((const OicUuid_t*) &lst->dev);
1300         printf("\n");
1301         lst = lst->next;
1302     }
1303     printf("\n");
1304
1305     return lst_cnt;
1306 }
1307
1308 static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
1309 {
1310     if(!rslt_lst || 0>=rslt_cnt)
1311     {
1312         printf("     Device List is Empty..\n\n");
1313         return 0;
1314     }
1315
1316     int lst_cnt = 0;
1317     for( ; rslt_cnt>lst_cnt; ++lst_cnt)
1318     {
1319         printf("     [%d] ", lst_cnt+1);
1320         printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
1321         printf(" - result: %d\n", rslt_lst[lst_cnt].res);
1322     }
1323     printf("\n");
1324
1325     return lst_cnt;
1326 }
1327
1328 static void printUuid(const OicUuid_t* uid)
1329 {
1330     for(int i=0; i<UUID_LENGTH; )
1331     {
1332         printf("%02X", (*uid).id[i++]);
1333         if(i==4 || i==6 || i==8 || i==10)  // canonical format for UUID has '8-4-4-4-12'
1334         {
1335             printf("-");
1336         }
1337     }
1338 }
1339
1340 static FILE* fopen_prvnMng(const char* path, const char* mode)
1341 {
1342     (void)path;  // unused |path| parameter
1343
1344     // input |g_svr_db_fname| internally by force, not using |path| parameter
1345     // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
1346     // with its own |SVR_DB_FILE_NAME|
1347     return fopen(SVR_DB_FILE_NAME, mode);
1348 }
1349
1350 static int waitCallbackRet(void)
1351 {
1352     for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
1353     {
1354         sleep(1);
1355         if(OC_STACK_OK != OCProcess())
1356         {
1357             OIC_LOG(ERROR, TAG, "OCStack process error");
1358             return -1;
1359         }
1360     }
1361
1362     return 0;
1363 }
1364
1365 static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
1366 {
1367     if(!a || !b || 2>max || !str)
1368     {
1369         return -1;
1370     }
1371
1372     for( ; ; )
1373     {
1374         for(int i=0; 2>i; ++i)
1375         {
1376             int* num = 0==i?a:b;
1377             for( ; ; )
1378             {
1379                 printf("   > Enter Device[%d] Number, %s: ", i+1, str);
1380                 for(int ret=0; 1!=ret; )
1381                 {
1382                     ret = scanf("%d", num);
1383                     for( ; 0x20<=getchar(); );  // for removing overflow garbages
1384                                                 // '0x20<=code' is character region
1385                 }
1386                 if(0<*num && max>=*num)
1387                 {
1388                     break;
1389                 }
1390                 printf("     Entered Wrong Number. Please Enter Again\n");
1391             }
1392         }
1393         if(*a != *b)
1394         {
1395             printf("\n");
1396             return 0;
1397         }
1398     }
1399
1400     return -1;
1401 }
1402
1403 static void printMenu(void)
1404 {
1405     printf("************************************************************\n");
1406     printf("****** OIC Provisioning Client with using C-level API ******\n");
1407     printf("************************************************************\n\n");
1408
1409     printf("** [A] DISCOVER DEVICES ON NETWORK\n");
1410     printf("** 10. Discover All Un/Owned Devices on Network\n");
1411     printf("** 11. Discover Only Unowned Devices on Network\n");
1412     printf("** 12. Discover Only Owned Devices on Network\n\n");
1413
1414     printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
1415     printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
1416
1417     printf("** [C] PROVISION/LINK PAIRWISE THINGS\n");
1418     printf("** 30. Provision/Link Pairwise Things\n");
1419     printf("** 31. Provision Credentials for Pairwise Things\n");
1420     printf("** 32. Provision the Selected Access Control List(ACL)\n");
1421     printf("** 33. Provision Direct-Pairing Configuration\n");
1422     printf("** 34. Check Linked Status of the Selected Device on PRVN DB\n\n");
1423
1424     printf("** [D] UNLINK PAIRWISE THINGS\n");
1425     printf("** 40. Unlink Pairwise Things\n\n");
1426
1427     printf("** [E] REMOVE THE SELECTED DEVICE\n");
1428     printf("** 50. Remove the Selected Device\n\n");
1429
1430     printf("** [F] GET SECURITY RESOURCE FOR DEBUGGING ONLY\n");
1431     printf("** 60. Get the Credential resources of the Selected Device\n");
1432     printf("** 61. Get the ACL resources of the Selected Device\n\n");
1433
1434     printf("** [F] EXIT PROVISIONING CLIENT\n");
1435     printf("** 99. Exit Provisionong Client\n\n");
1436
1437     printf("************************************************************\n\n");
1438 }
1439
1440 #if 0 // Code for enabling path configuration for PDB and SVR DBf
1441 static void printUsage(void)
1442 {
1443     printf("\n");
1444     printf("OIC Provisioning Client with using C-level API\n");
1445     printf("Usage: provisioningclient [option]...\n");
1446     printf("\n");
1447     printf("  -h                           print help for this provisioning client\n");
1448     printf("  -p=[prvn_db_file_path/name]  input PRVN DB file path and name\n");
1449     printf("                               if not exists, will load default DB file\n");
1450     printf("                               (default: |oic_prvn_mng.db| on working dir)\n");
1451     printf("                               (ex. -p=oic_prvn_mng.db)\n");
1452     printf("  -s=[svr_db_file_path/name]   input SVR DB file path and name\n");
1453     printf("                               if not exists, will load default DB file\n");
1454     printf("                               (default: |oic_svr_db_client.json| on working dir)\n");
1455     printf("                               (ex. -s=oic_svr_db_client.json)\n");
1456     printf("\n");
1457 }
1458 #endif
1459
1460 // main function for provisioning client using C-level provisioning API
1461 int main()
1462 {
1463     // initialize provisioning client
1464     if(initProvisionClient())
1465     {
1466         OIC_LOG(ERROR, TAG, "ProvisionClient init error");
1467         goto PMCLT_ERROR;
1468     }
1469
1470     // main loop for provisioning manager
1471     int mn_num = 0;
1472     for( ; ; )
1473     {
1474         printf("\n");
1475         printMenu();
1476         printf(">> Enter Menu Number: ");
1477         for(int ret=0; 1!=ret; )
1478         {
1479             ret = scanf("%d", &mn_num);
1480             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1481                                         // '0x20<=code' is character region
1482         }
1483         printf("\n");
1484         switch(mn_num)
1485         {
1486         case _10_DISCOV_ALL_DEVS_:
1487             if(discoverAllDevices())
1488             {
1489                 OIC_LOG(ERROR, TAG, "_10_DISCOV_ALL_DEVS_: error");
1490             }
1491             break;
1492         case _11_DISCOV_UNOWN_DEVS_:
1493             if(discoverUnownedDevices())
1494             {
1495                 OIC_LOG(ERROR, TAG, "_11_DISCOV_UNOWN_DEVS_: error");
1496             }
1497             break;
1498         case _12_DISCOV_OWN_DEVS_:
1499             if(discoverOwnedDevices())
1500             {
1501                 OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
1502             }
1503             break;
1504         case _20_REGIST_DEVS_:
1505             if(registerDevices())
1506             {
1507                 OIC_LOG(ERROR, TAG, "_20_REGIST_DEVS_: error");
1508             }
1509             break;
1510         case _30_PROVIS_PAIR_DEVS_:
1511             if(provisionPairwise())
1512             {
1513                 OIC_LOG(ERROR, TAG, "_30_PROVIS_PAIR_DEVS_: error");
1514             }
1515             break;
1516         case _31_PROVIS_CRED_:
1517             if(provisionCred())
1518             {
1519                 OIC_LOG(ERROR, TAG, "_31_PROVIS_CRED_: error");
1520             }
1521             break;
1522         case _32_PROVIS_ACL_:
1523             if(provisionAcl())
1524             {
1525                 OIC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
1526             }
1527             break;
1528         case _33_PROVIS_DP_:
1529             if(provisionDirectPairing())
1530             {
1531                 OIC_LOG(ERROR, TAG, "_33_PROVIS_DP_: error");
1532             }
1533             break;
1534         case _34_CHECK_LINK_STATUS_:
1535             if(checkLinkedStatus())
1536             {
1537                 OIC_LOG(ERROR, TAG, "_34_CHECK_LINK_STATUS_: error");
1538             }
1539             break;
1540         case _40_UNLINK_PAIR_DEVS_:
1541             if(unlinkPairwise())
1542             {
1543                 OIC_LOG(ERROR, TAG, "_40_UNLINK_PAIR_DEVS_: error");
1544             }
1545             break;
1546         case _50_REMOVE_SELEC_DEV_:
1547             if(removeDevice())
1548             {
1549                 OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
1550             }
1551             break;
1552         case _60_GET_CRED_:
1553             if(getCred())
1554             {
1555                 OIC_LOG(ERROR, TAG, "_60_GET_CRED_: error");
1556             }
1557             break;
1558         case _61_GET_ACL_:
1559             if(getAcl())
1560             {
1561                 OIC_LOG(ERROR, TAG, "_61_GET_ACL_: error");
1562             }
1563             break;
1564         case _99_EXIT_PRVN_CLT_:
1565             goto PMCLT_ERROR;
1566         default:
1567             printf(">> Entered Wrong Number. Please Enter Again\n\n");
1568             break;
1569         }
1570     }
1571
1572 PMCLT_ERROR:
1573     if(OC_STACK_OK != OCStop())
1574     {
1575         OIC_LOG(ERROR, TAG, "OCStack stop error");
1576     }
1577     OCDeleteDiscoveredDevices(g_own_list);  // after here |g_own_list| points nothing
1578     OCDeleteDiscoveredDevices(g_unown_list);  // after here |g_unown_list| points nothing
1579
1580     if(g_svr_fname)
1581     {
1582         OICFree(g_svr_fname);  // after here |g_svr_fname| points nothing
1583     }
1584     if(g_prvn_fname)
1585     {
1586         OICFree(g_prvn_fname);  // after here |g_prvn_fname| points nothing
1587     }
1588     return 0;  // always return normal case
1589 }
1590
1591 #ifdef __cplusplus
1592 }
1593 #endif //__cplusplus