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