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