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