Imported Upstream version 1.1.1
[platform/upstream/iotivity.git] / resource / provisioning / examples / provisioningclient.cpp
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 #include <string>
25 #include <map>
26 #include <cstdlib>
27 #include <pthread.h>
28 #include <mutex>
29 #include <condition_variable>
30
31 #include "logger.h"
32 #include "oic_malloc.h"
33 #include "oic_string.h"
34 #include "OCPlatform.h"
35 #include "OCApi.h"
36 #include "OCProvisioningManager.h"
37 #include "oxmjustworks.h"
38 #include "oxmrandompin.h"
39 #include "aclresource.h"
40 #include "utlist.h"
41
42 #define MAX_URI_LENGTH (64)
43 #define MAX_PERMISSION_LENGTH (5)
44 #define ACL_RESRC_ARRAY_SIZE (3)
45 #define CREATE (1)
46 #define READ (2)
47 #define UPDATE (4)
48 #define DELETE (8)
49 #define NOTIFY (16)
50 #define DASH '-'
51 #define PREDEFINED_TIMEOUT (10)
52 #define MAX_OWNED_DEVICE (10)
53 #define TAG  "provisioningclient"
54
55 #define JSON_DB_PATH "./oic_svr_db_client.json"
56 #define DAT_DB_PATH "./oic_svr_db_client.dat"
57 #define DEV_STATUS_ON "DEV_STATUS_ON"
58 #define DEV_STATUS_OFF "DEV_STATUS_OFF"
59
60 #define DISCOVERY_TIMEOUT 5
61
62 static const OicSecPrm_t  SUPPORTED_PRMS[1] =
63 {
64     PRM_PRE_CONFIGURED,
65 };
66
67 using namespace OC;
68
69 DeviceList_t pUnownedDevList, pOwnedDevList;
70 static int transferDevIdx, ask = 1;
71 static OicSecPconf_t g_pconf;
72
73 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
74 {
75     (void)UNUSED_PARAM;
76     return fopen(DAT_DB_PATH, mode);
77 }
78
79 void printMenu()
80 {
81     std::cout << "\nChoose an option:"<<std::endl;
82     std::cout << "   1. UnOwned Device discovery"<<std::endl;
83     std::cout << "   2. Owned Device discovery"<<std::endl;
84     std::cout << "   3. Ownership transfer"<<std::endl;
85     std::cout << "   4. Provision ACL"<<std::endl;
86     std::cout << "   5. Provision Credentials"<<std::endl;
87     std::cout << "   6. Credential & ACL provisioning b/w two devices"<<std::endl;
88     std::cout << "   7. Unlink Devices"<<std::endl;
89     std::cout << "   8. Remove Device"<<std::endl;
90     std::cout << "   9. Remove Device using UUID"<<std::endl;
91     std::cout << "  10. Get Linked Devices"<<std::endl;
92     std::cout << "  11. Get Device Status"<<std::endl;
93     std::cout << "  12. Provision Direct-Pairing Configuration"<<std::endl;
94     std::cout << "  13. Exit loop"<<std::endl;
95 }
96
97 void moveTransferredDevice()
98 {
99     pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);
100     pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
101 }
102
103 void InputPinCB(char* pinBuf, size_t bufSize)
104 {
105     if(pinBuf)
106     {
107         std::cout <<"INPUT PIN : ";
108         std::string ptr;
109         std::cin >> ptr;
110         OICStrcpy(pinBuf, bufSize, ptr.c_str());
111         return;
112     }
113 }
114
115 void printUuid(OicUuid_t uuid)
116 {
117     for (int i = 0; i < UUID_LENGTH; i++)
118     {
119         std::cout <<std::hex << uuid.id[i] << " ";
120     }
121     std::cout<<std::endl;
122 }
123
124 void ownershipTransferCB(PMResultList_t *result, int hasError)
125 {
126     if (hasError)
127     {
128         std::cout << "Error!!! in OwnershipTransfer"<<std::endl;
129     }
130     else
131     {
132         std::cout<< "\nTransferred Ownership successfuly for device : ";
133         printUuid(result->at(0).deviceId);
134         delete result;
135
136         moveTransferredDevice();
137     }
138     ask = 1;
139 }
140
141 void printStatus(int status)
142 {
143     static std::map<int, std::string> devStatus = {{1<<0, DEV_STATUS_ON}, {1<<1, DEV_STATUS_OFF}};
144
145     std::cout <<devStatus[status] <<std::endl;
146 }
147
148 void printDevices(DeviceList_t &list)
149 {
150    for (unsigned int i = 0; i < list.size(); i++ )
151    {
152       std::cout << "Device "<< i+1 <<" ID: ";
153       std::cout << list[i]->getDeviceID() << " From IP: ";
154       std::cout << list[i]->getDevAddr() << std::endl;
155    }
156 }
157
158 /**
159  * Callback function for provisioning ACL, Credentials.
160  *
161  * @param[in]    result Result list
162  * @param[in] hasError indicates if the result has error
163  */
164 void provisionCB(PMResultList_t *result, int hasError)
165 {
166    if (hasError)
167    {
168        std::cout << "Error in provisioning operation!"<<std::endl;
169    }
170    else
171    {
172        std::cout<< "\nReceived provisioning results: ";
173        for (unsigned int i = 0; i < result->size(); i++)
174        {
175            std::cout << "Result is = " << result->at(i).res <<" for device ";
176            printUuid(result->at(i).deviceId);
177        }
178
179        delete result;
180    }
181    printMenu();
182    ask = 1;
183 }
184 /**
185  *
186  * Ask user with which devices it wants to make further actions.
187  * All possible error checks included.
188  * Default behavior in case if only one options leaves are included too.
189  * Expect that user count devices from 1, f.e. 1st, 2nd, 3rd, etc
190  * Use DeviceList_t instead of devicesCount because of print devices info
191  *
192  * @param[in] list owned devices list.
193  * @param[out] out device number array.
194  * @param[in] count how many device numbers need to read.
195  * @return 0 in case of success and other value otherwise.
196  */
197 int readDeviceNumber(DeviceList_t &list, int count, int *out)
198 {
199    if (out == NULL || count <= 0)
200    {
201       std::cout << "Error! Please put valid input parameters" << std::endl;
202       return -1;
203    }
204
205    int devicesCount = list.size();
206
207    //Print current list of owned devices
208    std::cout <<"Owned devices, count = " << devicesCount << std::endl;
209    printDevices(list);
210
211    if (devicesCount < count)
212    {
213       std::cout << "You can't proceed with selected action because Owned devices count ( ";
214       std::cout << devicesCount << " ) are less then required devices ( " << count << " ).";
215       std::cout << "You may need to discover devices again" << std::endl;
216       return -2;
217    }
218
219    std::cout << "Select " << count << " device(s) for provisioning" << std::endl;
220
221    for (int curr = 0; curr < count; curr++)
222    {
223       //select last device by default if only 1 option exist
224       //from user's point of view device counting starts from 1,
225       //so 1st, 2nd, 3rd, etc devices
226       if ((curr == count - 1) && (devicesCount == count))
227       {
228          int sum = 0;
229          for (int i = 0; i < curr; i++)
230          {
231              sum += out[i];
232          }
233
234          out[curr] = (count*(count+1))/2 - sum;
235
236          std::cout << "Device " << curr + 1 << " : " << out[curr];
237          std::cout << " - selected automatically (because no other options exist)" << std::endl;
238          break;
239       }
240
241       int choice;
242       std::cout << "Device " << curr + 1 << " : ";
243       std::cin >> choice;
244
245       if (choice < 1 || choice > devicesCount)
246       {
247          std::cout << "Error! You should enter valid device number!" << std::endl;
248          return -3;
249       }
250
251       //check that user doesn't select the same device twice
252       for (int i = 0; i < curr; i++)
253       {
254          if (out[i] == choice)
255          {
256             std::cout << "Error! You cannot select the same device twice!" << std::endl;
257             return -4;
258          }
259       }
260
261       out[curr] = choice;
262    }
263
264    //Users count devices from 1, so 1st, 2nd, 3rd, etc device
265    //But deviceList array start index is 0, so need to decrease all numbers to 1
266    for (int i = 0; i < count; i++) out[i] -= 1;
267
268    return 0;
269 }
270
271 /**
272  * Perform cleanup for ACL
273  * @param[in]    ACL
274  */
275 static void deleteACL(OicSecAcl_t *acl)
276 {
277     DeleteACLList(acl);
278
279 }
280
281 /**
282  * Calculate ACL permission from string to bit
283  *
284  * @param[in] temp_psm    Input data of ACL permission string
285  * @param[in,out] pms    The pointer of ACL permission value
286  * @return  0 on success otherwise -1.
287  */
288 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
289 {
290     int i = 0;
291
292     if (NULL == temp_pms || NULL == pms)
293     {
294         return -1;
295     }
296     *pms = 0;
297     while (temp_pms[i] != '\0')
298     {
299         switch (temp_pms[i])
300         {
301             case 'C':
302                 {
303                     *pms += CREATE;
304                     i++;
305                     break;
306                 }
307             case 'R':
308                 {
309                     *pms += READ;
310                     i++;
311                     break;
312                 }
313             case 'U':
314                 {
315                     *pms += UPDATE;
316                     i++;
317                     break;
318                 }
319             case 'D':
320                 {
321                     *pms += DELETE;
322                     i++;
323                     break;
324                 }
325             case 'N':
326                 {
327                     *pms += NOTIFY;
328                     i++;
329                     break;
330                 }
331             case '_':
332                 {
333                     i++;
334                     break;
335                 }
336             default:
337                 {
338                     return -1;
339                 }
340         }
341     }
342     return 0;
343 }
344
345 /**
346  * Get the ACL property from user
347  *
348  * @param[in]    ACL Datastructure to save user inputs
349  * @return  0 on success otherwise -1.
350  */
351 static int InputACL(OicSecAcl_t *acl)
352 {
353     int ret;
354     char *temp_id, *temp_rsc, *temp_pms;
355
356     printf("******************************************************************************\n");
357     printf("-Set ACL policy for target device\n");
358     printf("******************************************************************************\n");
359     //Set Subject.
360     printf("-URN identifying the subject\n");
361     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
362     printf("Subject : ");
363     ret = scanf("%19ms", &temp_id);
364
365     OicSecAce_t* ace = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t));
366     if(NULL == ace)
367     {
368         OIC_LOG(ERROR, TAG, "Error while memory allocation");
369         return -1;
370     }
371     LL_APPEND(acl->aces, ace);
372
373     if (1 == ret)
374     {
375         for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
376         {
377             if (DASH != temp_id[i])
378                 ace->subjectuuid.id[j++] = temp_id[i];
379         }
380         OICFree(temp_id);
381     }
382     else
383     {
384         deleteACL(acl);
385         printf("Error while input\n");
386         return -1;
387     }
388
389     //Set Resource.
390     size_t resourcesLen = 0;
391     printf("Num. of Resource : ");
392     ret = scanf("%zu", &resourcesLen);
393     if ((1 != ret) || (resourcesLen <= 0 || resourcesLen > 50))
394     {
395         deleteACL(acl);
396         printf("Error while input\n");
397         return -1;
398     }
399     printf("-URI of resource\n");
400     printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
401     for(size_t i = 0; i < resourcesLen; i++)
402     {
403         OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
404         if(NULL == rsrc)
405         {
406             deleteACL(acl);
407             OIC_LOG(ERROR, TAG, "Error while memory allocation");
408             return -1;
409         }
410
411         LL_APPEND(ace->resources, rsrc);
412
413         printf("[%zu]Resource : ", i + 1);
414         ret = scanf("%64ms", &temp_rsc);
415         if (1 != ret)
416         {
417             printf("Error while input\n");
418             return -1;
419         }
420
421         rsrc->href = OICStrdup(temp_rsc);
422         OICFree(temp_rsc);
423
424         char* rsrc_in = NULL;
425         int arrLen = 0;
426         while(1)
427         {
428             printf("         Enter Number of resource type for [%s]: ", rsrc->href );
429             for(int ret=0; 1!=ret; )
430             {
431                 ret = scanf("%d", &arrLen);
432                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
433                                             // '0x20<=code' is character region
434             }
435             if(0 < arrLen && ACL_RESRC_ARRAY_SIZE >= arrLen)
436             {
437                 break;
438             }
439             printf("     Entered Wrong Number. Please Enter under %d Again\n", ACL_RESRC_ARRAY_SIZE);
440         }
441
442         rsrc->typeLen = arrLen;
443         rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
444         if(!rsrc->types)
445         {
446             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
447             goto error;
448         }
449
450         for(int i = 0; i < arrLen; i++)
451         {
452             printf("         Enter ResourceType[%d] Name (e.g. core.led): ", i+1);
453             for(int ret=0; 1!=ret; )
454             {
455                 ret = scanf("%64ms", &rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
456                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
457                                             // '0x20<=code' is character region
458             }
459             rsrc->types[i] = OICStrdup(rsrc_in);
460             OICFree(rsrc_in);
461             if(!rsrc->types[i])
462             {
463                 OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
464                 goto error;
465             }
466         }
467
468         while(1)
469         {
470             printf("         Enter Number of interface name for [%s]: ", rsrc->href);
471             for(int ret=0; 1!=ret; )
472             {
473                 ret = scanf("%d", &arrLen);
474                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
475                                             // '0x20<=code' is character region
476             }
477             if(0 < arrLen && ACL_RESRC_ARRAY_SIZE >= arrLen)
478             {
479                 break;
480             }
481             printf("     Entered Wrong Number. Please Enter under %d Again\n", ACL_RESRC_ARRAY_SIZE);
482         }
483
484         rsrc->interfaceLen = arrLen;
485         rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
486         if(!rsrc->interfaces)
487         {
488             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
489             goto error;
490         }
491
492         for(int i = 0; i < arrLen; i++)
493         {
494             printf("         Enter interfnace[%d] Name (e.g. oic.if.baseline): ", i+1);
495             for(int ret=0; 1!=ret; )
496             {
497                 ret = scanf("%64ms", &rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
498                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
499                                             // '0x20<=code' is character region
500             }
501             rsrc->interfaces[i] = OICStrdup(rsrc_in);
502             OICFree(rsrc_in);
503             if(!rsrc->interfaces[i])
504             {
505                 OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
506                 goto error;
507             }
508         }
509
510     }
511
512     // Set Permission
513     do
514     {
515         printf("-Set the permission(C,R,U,D,N)\n");
516         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
517         printf("Permission : ");
518         ret = scanf("%5ms", &temp_pms);
519         if (1 != ret)
520         {
521             printf("Error while input\n");
522             goto error;
523         }
524         ret = CalculateAclPermission(temp_pms, &(ace->permission));
525         OICFree(temp_pms);
526     } while (0 != ret );
527
528     // Set Rowner
529     printf("-URN identifying the rowner\n");
530     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
531
532     printf("Rowner : ");
533     ret = scanf("%19ms", &temp_id);
534     if (1 != ret)
535     {
536         printf("Error while input\n");
537         goto error;
538     }
539
540     for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
541     {
542         if (DASH != temp_id[k])
543         {
544             acl->rownerID.id[j++] = temp_id[k];
545         }
546     }
547     OICFree(temp_id);
548
549     return 0;
550
551 error:
552     DeleteACLList(acl);
553     return -1;
554 }
555
556 static int InputCredentials(Credential &cred)
557 {
558    int choice;
559
560    do
561    {
562        std::cout << "Select credential type from following values:" << std::endl;
563        std::cout << "1:  symmetric pair-wise key" << std::endl;
564        std::cout << "2:  symmetric group key" << std::endl;
565        std::cout << "4:  asymmetric key" << std::endl;
566        std::cout << "8:  signed asymmetric key (aka certificate)" << std::endl;
567        std::cout << "16: PIN /password" << std::endl;
568        std::cout << "Your choice: ";
569
570        std::cin >> choice;
571
572        switch (choice){
573            case 1:
574                cred.setCredentialType(static_cast<OicSecCredType_t>(choice));
575                choice = 0; //validation of the accepted choice.
576                break;
577            case 2:
578            case 4:
579            case 8:
580            case 16:
581                std::cout << "selected type is not supported yet" << std::endl;
582                break;
583            default:
584                std::cout << "Error! Please select valid credential type" << std::endl;
585                break;
586        }
587    } while(0 != choice);
588
589    std::cout << "Please enter key size (valid size is 128 or 256) :";
590    std::cin >> choice;
591
592    if(128 == choice)
593    {
594        cred.setCredentialKeySize(OWNER_PSK_LENGTH_128);
595    }
596    else if(256 == choice)
597    {
598         cred.setCredentialKeySize(OWNER_PSK_LENGTH_256);
599    }
600    else
601    {
602       std::cout << "Error! Please enter valid key size!" << std::endl;
603       return -2;
604    }
605
606    return 0;
607 }
608
609 static void deletePconf()
610 {
611     OICFree(g_pconf.prm);
612     //free pdacl
613     OicSecPdAcl_t* acl = g_pconf.pdacls;
614     if (acl)
615     {
616         /* Clean Resources */
617         for (unsigned int i = 0; i < (acl)->resourcesLen; i++)
618         {
619             OICFree((acl)->resources[i]);
620         }
621         OICFree((acl)->resources);
622
623         /* Clean ACL node itself */
624         /* Required only if acl was created in heap */
625         OICFree((acl));
626     }
627     memset(&g_pconf, 0, sizeof(OicSecPconf_t));
628 }
629
630 static OicSecPdAcl_t* InputPdACL()
631 {
632     int ret;
633     char *temp_rsc, *temp_pms;
634
635     printf("******************************************************************************\n");
636     printf("-Set ACL policy for target DP device\n");
637     printf("******************************************************************************\n");
638
639     OicSecPdAcl_t *acl = (OicSecPdAcl_t *)OICCalloc(1,sizeof(OicSecPdAcl_t));
640     if (NULL == acl)
641     {
642         OIC_LOG(ERROR, TAG, "Error while memory allocation");
643         return NULL;
644     }
645
646     //Set Resource.
647     printf("Num. of Resource : ");
648     ret = scanf("%zu", &acl->resourcesLen);
649     if ((1 != ret) || (acl->resourcesLen <= 0 || acl->resourcesLen > 50))
650     {
651         printf("Error while input\n");
652         OICFree(acl);
653         return NULL;
654     }
655     printf("-URI of resource\n");
656     printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
657     acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
658     if (NULL == acl->resources)
659     {
660         OIC_LOG(ERROR, TAG, "Error while memory allocation");
661         OICFree(acl);
662         return NULL;
663     }
664     for (size_t i = 0; i < acl->resourcesLen; i++)
665     {
666         printf("[%zu]Resource : ", i + 1);
667         ret = scanf("%64ms", &temp_rsc);
668         if (1 != ret)
669         {
670             printf("Error while input\n");
671             OICFree(acl->resources);
672             OICFree(acl);
673             return NULL;
674         }
675
676         acl->resources[i] = OICStrdup(temp_rsc);
677         OICFree(temp_rsc);
678         if (NULL == acl->resources[i])
679         {
680             OIC_LOG(ERROR, TAG, "Error while memory allocation");
681             OICFree(acl->resources);
682             OICFree(acl);
683             return NULL;
684         }
685     }
686
687     // Set Permission
688     do
689     {
690         printf("-Set the permission(C,R,U,D,N)\n");
691         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
692         printf("Permission : ");
693         ret = scanf("%5ms", &temp_pms);
694         if (1 != ret)
695         {
696             printf("Error while input\n");
697             OICFree(acl->resources);
698             OICFree(acl);
699             return NULL;
700         }
701         ret = CalculateAclPermission(temp_pms, &(acl->permission));
702         OICFree(temp_pms);
703     } while (0 != ret );
704
705     return acl;
706 }
707
708 void provisionDirectPairingCB(PMResultList_t *result, int hasError)
709 {
710     if (hasError)
711     {
712         std::cout << "Error in provisioning operation!"<<std::endl;
713     }
714     else
715     {
716         std::cout<< "\nReceived provisioning results: Direct Pairing is successful ";
717         for (unsigned int i = 0; i < result->size(); i++)
718         {
719             std::cout << "Result is = " << result->at(i).res <<" for device ";
720             printUuid(result->at(i).deviceId);
721         }
722
723         delete result;
724     }
725     deletePconf();
726     printMenu();
727     ask = 1;
728 }
729
730 static void provisionDP(int dev_num)
731 {
732     OCStackResult rst;
733     std::string pin("");
734
735     // set enable dp
736     g_pconf.edp = true;
737
738     // set default supported PRM types
739     g_pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
740     g_pconf.prm = (OicSecPrm_t *)OICCalloc(g_pconf.prmLen, sizeof(OicSecPrm_t));
741     if(g_pconf.prm)
742     {
743         for (size_t i=0; i < g_pconf.prmLen; i++)
744         {
745             g_pconf.prm[i] = SUPPORTED_PRMS[i];
746         }
747     }
748     else
749     {
750         OIC_LOG(ERROR, TAG, "create prm error return");
751         goto PVDP_ERROR;
752     }
753
754     std::cout << "Enter PIN to be configured: ";
755     while (1)
756     {
757         std::cin >> pin;
758         if (pin.length() == DP_PIN_LENGTH)
759         {
760             break;
761         }
762         else
763         {
764             std::cout << "PIN length should be 8, Enter again: ";
765         }
766     }
767
768     memcpy(g_pconf.pin.val, pin.c_str(), DP_PIN_LENGTH);
769
770     // set default pdacl
771
772     g_pconf.pdacls = InputPdACL();
773     if(!g_pconf.pdacls)
774     {
775         OIC_LOG(ERROR, TAG, "InputPdACL error return");
776         goto PVDP_ERROR;
777     }
778
779     // call |OCProvisionDirectPairing| API actually
780     // calling this API with callback actually acts like blocking
781     // for error checking, the return value saved and printed
782     rst = pOwnedDevList[dev_num-1]->provisionDirectPairing(&g_pconf, provisionDirectPairingCB);
783     if(OC_STACK_OK != rst)
784     {
785         OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
786         if (OC_STACK_UNAUTHORIZED_REQ == rst)
787         {
788             OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
789         }
790         goto PVDP_ERROR;
791     }
792     return;
793
794 PVDP_ERROR:
795     deletePconf();  // after here |acl| points nothing
796     ask = 1;
797 }
798
799 int main(void)
800 {
801     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
802
803     // Create PlatformConfig object
804     PlatformConfig cfg {
805         OC::ServiceType::InProc,
806             OC::ModeType::Both,
807             "0.0.0.0",
808             0,
809             OC::QualityOfService::LowQos,
810             &ps
811     };
812
813     OCPlatform::Configure(cfg);
814
815     try
816     {
817         int choice;
818         OicSecAcl_t *acl1 = nullptr, *acl2 = nullptr;
819         if (OCSecure::provisionInit("") != OC_STACK_OK)
820         {
821             std::cout <<"PM Init failed"<< std::endl;
822             return 1;
823         }
824
825         for (int out = 0; !out;)
826         {
827             while (!ask)
828             {
829                 sleep(1);
830             }
831
832             if (acl1)
833             {
834                 deleteACL(acl1);
835                 acl1 = nullptr;
836             }
837
838             if (acl2)
839             {
840                 deleteACL(acl2);
841                 acl2 = nullptr;
842             }
843
844             printMenu();
845             std::cin >> choice;
846             switch(choice) {
847                 case 1:
848                     {
849                         //Secure resource discovery.
850
851                         pUnownedDevList.clear();
852                         std::cout << "Started discovery..." <<std::endl;
853                         OCStackResult result = OCSecure::discoverUnownedDevices(DISCOVERY_TIMEOUT,
854                                 pUnownedDevList);
855                         if (result != OC_STACK_OK)
856                         {
857                             std::cout<< "!!Error - UnOwned Discovery failed."<<std::endl;
858                         }
859                         else if (pUnownedDevList.size())
860                         {
861                             std::cout <<"Found secure devices, count = " <<
862                                 pUnownedDevList.size() << std::endl;
863                             printDevices(pUnownedDevList);
864                         }
865                         else
866                         {
867                             std::cout <<"No Secure devices found"<<std::endl;
868                         }
869                         break;
870                     }
871                 case 2:
872                     {
873                         pOwnedDevList.clear();
874                         std::cout << "Started discovery..." <<std::endl;
875                         OCStackResult result = OCSecure::discoverOwnedDevices(DISCOVERY_TIMEOUT,
876                                 pOwnedDevList);
877                         if (result != OC_STACK_OK)
878                         {
879                             std::cout<< "!!Error - Owned Discovery failed."<<std::endl;
880                         }
881                         else if (pOwnedDevList.size())
882                         {
883                             std::cout <<"Found owned devices, count = " <<
884                                 pOwnedDevList.size() << std::endl;
885                             printDevices(pOwnedDevList);
886                         }
887                         else
888                         {
889                             std::cout <<"No Secure devices found"<<std::endl;
890                         }
891                         break;
892                     }
893                 case 3:
894                     {
895                         unsigned int devNum;
896
897                         if (!pUnownedDevList.size())
898                         {
899                             std::cout <<"There are no more Unowned devices"<<std::endl;
900                             break;
901                         }
902
903                         for (unsigned int i = 0; i < pUnownedDevList.size(); i++ )
904                         {
905                             std::cout << i+1 << ": "<< pUnownedDevList[i]->getDeviceID();
906                             std::cout << " From IP:" << pUnownedDevList[i]->getDevAddr() <<std::endl;
907                         }
908
909                         std::cout <<"Select device number: "<<std::endl;
910                         std::cin >> devNum;
911                         if (devNum > pUnownedDevList.size())
912                         {
913                             std::cout <<"Invalid device number"<<std::endl;
914                             break;
915                         }
916                         transferDevIdx = devNum - 1;
917
918                         //register callbacks for JUST WORKS and PIN methods
919                         std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
920
921                         {
922                             OTMCallbackData_t justWorksCBData;
923                             justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
924                             justWorksCBData.createSecureSessionCB =
925                                 CreateSecureSessionJustWorksCallback;
926                             justWorksCBData.createSelectOxmPayloadCB =
927                                 CreateJustWorksSelectOxmPayload;
928                             justWorksCBData.createOwnerTransferPayloadCB =
929                                 CreateJustWorksOwnerTransferPayload;
930                             OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
931                                     &justWorksCBData, NULL);
932                         }
933
934                         {
935                             OTMCallbackData_t pinBasedCBData;
936                             pinBasedCBData.loadSecretCB = InputPinCodeCallback;
937                             pinBasedCBData.createSecureSessionCB =
938                                 CreateSecureSessionRandomPinCallback;
939                             pinBasedCBData.createSelectOxmPayloadCB =
940                                 CreatePinBasedSelectOxmPayload;
941                             pinBasedCBData.createOwnerTransferPayloadCB =
942                                 CreatePinBasedOwnerTransferPayload;
943                             OCSecure::setOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN,
944                                     &pinBasedCBData, InputPinCB);
945                         }
946
947                         ask = 0;
948                         std::cout << "Transfering ownership for : "<<
949                             pUnownedDevList[devNum-1]->getDeviceID()<<std::endl;
950                         if (pUnownedDevList[devNum-1]->doOwnershipTransfer(ownershipTransferCB)
951                                 != OC_STACK_OK)
952                         {
953                             std::cout<<"OwnershipTransferCallback is failed"<<std::endl;
954                             ask = 1;
955                         }
956                         break;
957                     }
958                 case 4: //Provision ACL
959                     {
960                         int index;
961
962                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
963
964                         std::cout << "Provision ACL for : "<<
965                             pOwnedDevList[index]->getDeviceID()<< std::endl;
966
967                         acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
968                         if (NULL == acl1)
969                         {
970                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
971                             break;
972                         }
973
974                         std::cout << "Please input ACL for selected device: " << std::endl;
975                         if (0 != InputACL(acl1))
976                         {
977                             break;
978                         }
979
980                         ask = 0;
981
982                         if (pOwnedDevList[index]->provisionACL(acl1, provisionCB) != OC_STACK_OK)
983                         {
984                             ask = 1;
985                             std::cout <<"provisionACL is failed"<< std::endl;
986                         }
987                     }
988                     break;
989                 case 5: //Provision Credentials
990                     {
991                         int devices[2];
992
993                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
994
995                         int first  = devices[0];
996                         int second = devices[1];
997
998                         std::cout << "Provision Credentials to devices: "<<
999                             pOwnedDevList[first]->getDeviceID();
1000                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
1001
1002                         Credential cred( NO_SECURITY_MODE ,0);
1003                         std::cout << "Please input credentials for selected devices: " << std::endl;
1004                         if (0 != InputCredentials(cred))
1005                             break;
1006
1007                         ask = 0;
1008
1009                         if (pOwnedDevList[first]->provisionCredentials(cred,
1010                                     *pOwnedDevList[second].get(), provisionCB) != OC_STACK_OK)
1011                         {
1012                             ask = 1;
1013                             std::cout <<"provisionCredentials is failed"<< std::endl;
1014                         }
1015                     }
1016                     break;
1017                 case 6: //Provision ACL & Creds b/w two devices.
1018                     {
1019                         int devices[2];
1020
1021                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
1022
1023                         int first  = devices[0];
1024                         int second = devices[1];
1025
1026                         std::cout << "Provision pairwise devices: "<<
1027                             pOwnedDevList[first]->getDeviceID();
1028                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
1029
1030                         Credential cred( NO_SECURITY_MODE, 0);
1031                         std::cout << "Please input credentials for selected devices: " << std::endl;
1032                         if (0 != InputCredentials(cred))
1033                             break;
1034
1035                         acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
1036                         if (NULL == acl1)
1037                         {
1038                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
1039                             break;
1040                         }
1041
1042                         std::cout << "Please input ACL for selected device: " << std::endl;
1043                         if (0 != InputACL(acl1))
1044                         {
1045                             break;
1046                         }
1047
1048                         acl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
1049                         if (NULL == acl2)
1050                         {
1051                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
1052                             break;
1053                         }
1054
1055                         std::cout << "Please input ACL for selected device: " << std::endl;
1056                         if (0 != InputACL(acl2))
1057                         {
1058                             break;
1059                         }
1060
1061                         ask = 0;
1062
1063                         if (pOwnedDevList[first]->provisionPairwiseDevices(cred, acl1,
1064                                     *pOwnedDevList[second].get(), acl2, provisionCB) != OC_STACK_OK)
1065                         {
1066                             ask = 1;
1067                             std::cout <<"provisionPairwiseDevices is failed"<< std::endl;
1068                         }
1069                     }
1070                     break;
1071                 case 7: //Unlink Devices
1072                     {
1073                         int devices[2];
1074
1075                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
1076
1077                         int first  = devices[0];
1078                         int second = devices[1];
1079
1080                         std::cout << "Unlink devices: "<< pOwnedDevList[first]->getDeviceID();
1081                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
1082
1083                         ask = 0;
1084
1085                         if (pOwnedDevList[first]->unlinkDevices(*pOwnedDevList[second].get(),
1086                                     provisionCB) != OC_STACK_OK)
1087                         {
1088                             ask = 1;
1089                             std::cout <<"unlinkDevice is failed"<< std::endl;
1090                         }
1091                         break;
1092                     }
1093                 case 8: //Remove Device
1094                     {
1095                         int index;
1096
1097                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
1098
1099                         std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
1100
1101                         ask = 0;
1102
1103                         if (pOwnedDevList[index]->removeDevice(DISCOVERY_TIMEOUT, provisionCB)
1104                                 != OC_STACK_OK)
1105                         {
1106                             ask = 1;
1107                             std::cout <<"removeDevice is failed"<< std::endl;
1108                         }
1109                         break;
1110                     }
1111                 case 9: //Remove Device using UUID
1112                     {
1113                         int index;
1114
1115                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
1116
1117                         std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
1118
1119                         ask = 0;
1120
1121                         if (pOwnedDevList[index]->removeDeviceWithUuid(DISCOVERY_TIMEOUT,
1122                                                                        pOwnedDevList[index]->getDeviceID(),
1123                                                                        provisionCB)
1124                                 != OC_STACK_OK)
1125                         {
1126                             ask = 1;
1127                             std::cout <<"removeDevice is failed"<< std::endl;
1128                         }
1129                         break;
1130                     }
1131
1132                 case 10: //Get Linked devices
1133                     {
1134                         UuidList_t linkedUuid;
1135                         unsigned int devNum;
1136
1137                         if (!pOwnedDevList.size())
1138                         {
1139                             std::cout <<"There are no Owned devices yet,"
1140                                 " may need to discover"<<std::endl;
1141                             break;
1142                         }
1143
1144                         for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
1145                         {
1146                             std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
1147                             std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
1148                         }
1149
1150                         std::cout <<"Select device number: "<<std::endl;
1151                         std::cin >> devNum;
1152                         if (devNum > pOwnedDevList.size())
1153                         {
1154                             std::cout <<"Invalid device number"<<std::endl;
1155                             break;
1156                         }
1157
1158                         if(pOwnedDevList[devNum  -1]->getLinkedDevices(linkedUuid) == OC_STACK_OK)
1159                         {
1160                             if (!linkedUuid.size())
1161                             {
1162                                 std::cout <<"No devices are linked to "<<
1163                                     pOwnedDevList[devNum  -1]->getDeviceID() << std::endl;
1164                             }
1165                             //display the Linked devices (UUIDs)
1166                             for(unsigned int i = 0; i < linkedUuid.size(); i++)
1167                             {
1168                                 printUuid(linkedUuid[i]);
1169                             }
1170                         }
1171                         else
1172                         {
1173                             std::cout <<"Error! in getLinkedDevices"<<std::endl;
1174                         }
1175                         break;
1176                     }
1177                 case 11: //Get device' status
1178                     {
1179                         DeviceList_t unownedList, ownedList;
1180
1181                         if (OCSecure::getDevInfoFromNetwork(DISCOVERY_TIMEOUT, ownedList,
1182                                     unownedList) == OC_STACK_OK)
1183                         {
1184                             std::cout <<"Owned Device' status for" <<std::endl;
1185                             for (unsigned int i = 0; i < ownedList.size(); i++ )
1186                             {
1187                                 std::cout << "Device "<<i+1 <<" ID: '";
1188                                 std::cout << ownedList[i]->getDeviceID() << "' From IP: ";
1189                                 std::cout << ownedList[i]->getDevAddr() << " Status: ";
1190                                 printStatus(ownedList[i]->getDeviceStatus());
1191                             }
1192                             std::cout <<"\nUnOwned Device' status for" <<std::endl;
1193                             for (unsigned int i = 0; i < unownedList.size(); i++ )
1194                             {
1195                                 std::cout << "Device "<<i+1 <<" ID: '";
1196                                 std::cout << unownedList[i]->getDeviceID() << "' From IP: ";
1197                                 std::cout << unownedList[i]->getDevAddr() << " Status: ";
1198                                 printStatus(unownedList[i]->getDeviceStatus());
1199                             }
1200
1201                         }
1202                         break;
1203                     }
1204
1205                 case 12:
1206                     {
1207                         unsigned int devNum;
1208
1209                         if (!pOwnedDevList.size())
1210                         {
1211                             std::cout <<"There are no Owned devices yet,"
1212                                 " may need to discover"<<std::endl;
1213                             break;
1214                         }
1215
1216                         for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
1217                         {
1218                             std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
1219                             std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
1220                         }
1221
1222                         std::cout <<"Select device number: "<<std::endl;
1223                         std::cin >> devNum;
1224                         if (devNum > pOwnedDevList.size())
1225                         {
1226                             std::cout <<"Invalid device number"<<std::endl;
1227                             break;
1228                         }
1229
1230                         ask = 0;
1231                         provisionDP(devNum);
1232
1233                         break;
1234                     }
1235                 case 13:
1236                 default:
1237                     out = 1;
1238                     break;
1239             }
1240         }
1241     }
1242     catch(OCException& e)
1243     {
1244         oclog() << "Exception in main: "<<e.what();
1245     }
1246
1247     return 0;
1248 }