e3b818594dfcf0cd8f1ab49b28c62ebc53daa84c
[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
40 #define MAX_URI_LENGTH (64)
41 #define MAX_PERMISSION_LENGTH (5)
42 #define CREATE (1)
43 #define READ (2)
44 #define UPDATE (4)
45 #define DELETE (8)
46 #define NOTIFY (16)
47 #define DASH '-'
48 #define PREDEFINED_TIMEOUT (10)
49 #define MAX_OWNED_DEVICE (10)
50 #define TAG  "provisioningclient"
51
52 #define JSON_DB_PATH "./oic_svr_db_client.json"
53 #define DEV_STATUS_ON "DEV_STATUS_ON"
54 #define DEV_STATUS_OFF "DEV_STATUS_OFF"
55
56 #define DISCOVERY_TIMEOUT 5
57
58 using namespace OC;
59
60 DeviceList_t pUnownedDevList, pOwnedDevList;
61 static int transferDevIdx, ask = 1;
62
63 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
64 {
65     (void)UNUSED_PARAM;
66     return fopen(JSON_DB_PATH, mode);
67 }
68
69 void printMenu()
70 {
71     std::cout << "\nChoose an option:"<<std::endl;
72     std::cout << "   1. UnOwned Device discovery"<<std::endl;
73     std::cout << "   2. Owned Device discovery"<<std::endl;
74     std::cout << "   3. Ownership transfer"<<std::endl;
75     std::cout << "   4. Provision ACL"<<std::endl;
76     std::cout << "   5. Provision Credentials"<<std::endl;
77     std::cout << "   6. Credential & ACL provisioning b/w two devices"<<std::endl;
78     std::cout << "   7. Unlink Devices"<<std::endl;
79     std::cout << "   8. Remove Device"<<std::endl;
80     std::cout << "   9. Get Linked Devices"<<std::endl;
81     std::cout << "   10. Get Device Status"<<std::endl;
82     std::cout << "   11. Exit loop"<<std::endl;
83 }
84
85 void moveTransferredDevice()
86 {
87     pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);
88     pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
89 }
90
91 void InputPinCB(char* pinBuf, size_t bufSize)
92 {
93     if(pinBuf)
94     {
95         std::cout <<"INPUT PIN : ";
96         std::string ptr;
97         std::cin >> ptr;
98         OICStrcpy(pinBuf, bufSize, ptr.c_str());
99         return;
100     }
101 }
102
103 void printUuid(OicUuid_t uuid)
104 {
105     for (int i = 0; i < UUID_LENGTH; i++)
106     {
107         std::cout <<std::hex << uuid.id[i] << " ";
108     }
109     std::cout<<std::endl;
110 }
111
112 void ownershipTransferCB(PMResultList_t *result, int hasError)
113 {
114     if (hasError)
115     {
116         std::cout << "Error!!! in OwnershipTransfer"<<std::endl;
117     }
118     else
119     {
120         std::cout<< "\nTransferred Ownership successfuly for device : ";
121         printUuid(result->at(0).deviceId);
122         delete result;
123
124         moveTransferredDevice();
125     }
126     ask = 1;
127 }
128
129 void printStatus(int status)
130 {
131     static std::map<int, std::string> devStatus = {{1<<0, DEV_STATUS_ON}, {1<<1, DEV_STATUS_OFF}};
132
133     std::cout <<devStatus[status] <<std::endl;
134 }
135
136 void printDevices(DeviceList_t &list)
137 {
138    for (unsigned int i = 0; i < list.size(); i++ )
139    {
140       std::cout << "Device "<< i+1 <<" ID: ";
141       std::cout << list[i]->getDeviceID() << " From IP: ";
142       std::cout << list[i]->getDevAddr() << std::endl;
143    }
144 }
145
146 /**
147  * Callback function for provisioning ACL, Credentials.
148  *
149  * @param[in]    result Result list
150  * @param[in] hasError indicates if the result has error
151  */
152 void provisionCB(PMResultList_t *result, int hasError)
153 {
154    if (hasError)
155    {
156        std::cout << "Error in provisioning operation!"<<std::endl;
157    }
158    else
159    {
160        std::cout<< "\nReceived provisioning results: ";
161        for (unsigned int i = 0; i < result->size(); i++)
162        {
163            std::cout << "Result is = " << result->at(i).res <<" for device ";
164            printUuid(result->at(i).deviceId);
165        }
166
167        delete result;
168    }
169    printMenu();
170    ask = 1;
171 }
172 /**
173  *
174  * Ask user with which devices it wants to make further actions.
175  * All possible error checks included.
176  * Default behavior in case if only one options leaves are included too.
177  * Expect that user count devices from 1, f.e. 1st, 2nd, 3rd, etc
178  * Use DeviceList_t instead of devicesCount because of print devices info
179  *
180  * @param[in] list owned devices list.
181  * @param[out] out device number array.
182  * @param[in] count how many device numbers need to read.
183  * @return 0 in case of success and other value otherwise.
184  */
185 int readDeviceNumber(DeviceList_t &list, int count, int *out)
186 {
187    if (out == NULL || count <= 0)
188    {
189       std::cout << "Error! Please put valid input parameters" << std::endl;
190       return -1;
191    }
192
193    int devicesCount = list.size();
194
195    //Print current list of owned devices
196    std::cout <<"Owned devices, count = " << devicesCount << std::endl;
197    printDevices(list);
198
199    if (devicesCount < count)
200    {
201       std::cout << "You can't proceed with selected action because Owned devices count ( ";
202       std::cout << devicesCount << " ) are less then required devices ( " << count << " ).";
203       std::cout << "You may need to discover devices again" << std::endl;
204       return -2;
205    }
206
207    std::cout << "Select " << count << " device(s) for provisioning" << std::endl;
208
209    for (int curr = 0; curr < count; curr++)
210    {
211       //select last device by default if only 1 option exist
212       //from user's point of view device counting starts from 1,
213       //so 1st, 2nd, 3rd, etc devices
214       if ((curr == count - 1) && (devicesCount == count))
215       {
216          int sum = 0;
217          for (int i = 0; i < curr; i++)
218          {
219              sum += out[i];
220          }
221
222          out[curr] = (count*(count+1))/2 - sum;
223
224          std::cout << "Device " << curr + 1 << " : " << out[curr];
225          std::cout << " - selected automatically (because no other options exist)" << std::endl;
226          break;
227       }
228
229       int choice;
230       std::cout << "Device " << curr + 1 << " : ";
231       std::cin >> choice;
232
233       if (choice < 1 || choice > devicesCount)
234       {
235          std::cout << "Error! You should enter valid device number!" << std::endl;
236          return -3;
237       }
238
239       //check that user doesn't select the same device twice
240       for (int i = 0; i < curr; i++)
241       {
242          if (out[i] == choice)
243          {
244             std::cout << "Error! You cannot select the same device twice!" << std::endl;
245             return -4;
246          }
247       }
248
249       out[curr] = choice;
250    }
251
252    //Users count devices from 1, so 1st, 2nd, 3rd, etc device
253    //But deviceList array start index is 0, so need to decrease all numbers to 1
254    for (int i = 0; i < count; i++) out[i] -= 1;
255
256    return 0;
257 }
258
259 /**
260  * Perform cleanup for ACL
261  * @param[in]    ACL
262  */
263 static void deleteACL(OicSecAcl_t *acl)
264 {
265     if (acl)
266     {
267         /* Clean Resources */
268         for (unsigned int i = 0; i < (acl)->resourcesLen; i++)
269         {
270             OICFree((acl)->resources[i]);
271         }
272         OICFree((acl)->resources);
273
274         /* Clean Owners */
275         OICFree((acl)->owners);
276
277         /* Clean ACL node itself */
278         /* Required only if acl was created in heap */
279         OICFree((acl));
280     }
281 }
282
283 /**
284  * Calculate ACL permission from string to bit
285  *
286  * @param[in] temp_psm    Input data of ACL permission string
287  * @param[in,out] pms    The pointer of ACL permission value
288  * @return  0 on success otherwise -1.
289  */
290 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
291 {
292     int i = 0;
293
294     if (NULL == temp_pms || NULL == pms)
295     {
296         return -1;
297     }
298     *pms = 0;
299     while (temp_pms[i] != '\0')
300     {
301         switch (temp_pms[i])
302         {
303             case 'C':
304                 {
305                     *pms += CREATE;
306                     i++;
307                     break;
308                 }
309             case 'R':
310                 {
311                     *pms += READ;
312                     i++;
313                     break;
314                 }
315             case 'U':
316                 {
317                     *pms += UPDATE;
318                     i++;
319                     break;
320                 }
321             case 'D':
322                 {
323                     *pms += DELETE;
324                     i++;
325                     break;
326                 }
327             case 'N':
328                 {
329                     *pms += NOTIFY;
330                     i++;
331                     break;
332                 }
333             case '_':
334                 {
335                     i++;
336                     break;
337                 }
338             default:
339                 {
340                     return -1;
341                 }
342         }
343     }
344     return 0;
345 }
346
347 /**
348  * Get the ACL property from user
349  *
350  * @param[in]    ACL Datastructure to save user inputs
351  * @return  0 on success otherwise -1.
352  */
353 static int InputACL(OicSecAcl_t *acl)
354 {
355     int ret;
356     char *temp_id, *temp_rsc, *temp_pms;
357
358     printf("******************************************************************************\n");
359     printf("-Set ACL policy for target device\n");
360     printf("******************************************************************************\n");
361     //Set Subject.
362     printf("-URN identifying the subject\n");
363     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
364     printf("Subject : ");
365     ret = scanf("%19ms", &temp_id);
366
367     if (1 == ret)
368     {
369         for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
370         {
371             if (DASH != temp_id[i])
372                 acl->subject.id[j++] = temp_id[i];
373         }
374         OICFree(temp_id);
375     }
376     else
377     {
378         printf("Error while input\n");
379         return -1;
380     }
381
382     //Set Resource.
383     printf("Num. of Resource : ");
384     ret = scanf("%zu", &acl->resourcesLen);
385     printf("-URI of resource\n");
386     printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
387     acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
388     if (NULL == acl->resources)
389     {
390         OIC_LOG(ERROR, TAG, "Error while memory allocation");
391         return -1;
392     }
393     for (size_t i = 0; i < acl->resourcesLen; i++)
394     {
395         printf("[%zu]Resource : ", i + 1);
396         ret = scanf("%64ms", &temp_rsc);
397         if (1 != ret)
398         {
399             printf("Error while input\n");
400             return -1;
401         }
402
403         acl->resources[i] = OICStrdup(temp_rsc);
404         OICFree(temp_rsc);
405         if (NULL == acl->resources[i])
406         {
407             OIC_LOG(ERROR, TAG, "Error while memory allocation");
408             return -1;
409         }
410     }
411     // Set Permission
412     do
413     {
414         printf("-Set the permission(C,R,U,D,N)\n");
415         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
416         printf("Permission : ");
417         ret = scanf("%5ms", &temp_pms);
418         if (1 != ret)
419         {
420             printf("Error while input\n");
421             return -1;
422         }
423         ret = CalculateAclPermission(temp_pms, &(acl->permission));
424         OICFree(temp_pms);
425     } while (0 != ret );
426
427     // Set Rowner
428     printf("Num. of Rowner : ");
429     ret = scanf("%zu", &acl->ownersLen);
430     printf("-URN identifying the rowner\n");
431     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
432     acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
433     if (NULL == acl->owners)
434     {
435         OIC_LOG(ERROR, TAG, "Error while memory allocation");
436         return -1;
437     }
438     for (size_t i = 0; i < acl->ownersLen; i++)
439     {
440         printf("[%zu]Rowner : ", i + 1);
441         ret = scanf("%19ms", &temp_id);
442         if (1 != ret)
443         {
444             printf("Error while input\n");
445             return -1;
446         }
447
448         for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
449         {
450             if (DASH != temp_id[k])
451             {
452                 acl->owners[i].id[j++] = temp_id[k];
453             }
454         }
455         OICFree(temp_id);
456     }
457     return 0;
458 }
459
460 static int InputCredentials(Credential &cred)
461 {
462    int choice;
463
464    do
465    {
466        std::cout << "Select credential type from following values:" << std::endl;
467        std::cout << "1:  symmetric pair-wise key" << std::endl;
468        std::cout << "2:  symmetric group key" << std::endl;
469        std::cout << "4:  asymmetric key" << std::endl;
470        std::cout << "8:  signed asymmetric key (aka certificate)" << std::endl;
471        std::cout << "16: PIN /password" << std::endl;
472        std::cout << "Your choice: ";
473
474        std::cin >> choice;
475
476        switch (choice){
477            case 1:
478                cred.setCredentialType(static_cast<OicSecCredType_t>(choice));
479                choice = 0; //validation of the accepted choice.
480                break;
481            case 2:
482            case 4:
483            case 8:
484            case 16:
485                std::cout << "selected type is not supported yet" << std::endl;
486                break;
487            default:
488                std::cout << "Error! Please select valid credential type" << std::endl;
489                break;
490        }
491    } while(0 != choice);
492
493    std::cout << "Please enter key size (valid size is 128 or 256) :";
494    std::cin >> choice;
495
496    if(128 == choice)
497    {
498        cred.setCredentialKeySize(OWNER_PSK_LENGTH_128);
499    }
500    else if(256 == choice)
501    {
502         cred.setCredentialKeySize(OWNER_PSK_LENGTH_256);
503    }
504    else
505    {
506       std::cout << "Error! Please enter valid key size!" << std::endl;
507       return -2;
508    }
509
510    return 0;
511 }
512
513 int main(void)
514 {
515     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
516
517     // Create PlatformConfig object
518     PlatformConfig cfg {
519         OC::ServiceType::InProc,
520             OC::ModeType::Both,
521             "0.0.0.0",
522             0,
523             OC::QualityOfService::LowQos,
524             &ps
525     };
526
527     OCPlatform::Configure(cfg);
528
529     try
530     {
531         int choice;
532         OicSecAcl_t *acl1 = nullptr, *acl2 = nullptr;
533         if (OCSecure::provisionInit("") != OC_STACK_OK)
534         {
535             std::cout <<"PM Init failed"<< std::endl;
536             return 1;
537         }
538
539         for (int out = 0; !out;)
540         {
541             while (!ask)
542             {
543                 sleep(1);
544             }
545
546             if (acl1)
547             {
548                 deleteACL(acl1);
549                 acl1 = nullptr;
550             }
551
552             if (acl2)
553             {
554                 deleteACL(acl2);
555                 acl2 = nullptr;
556             }
557
558             printMenu();
559             std::cin >> choice;
560             switch(choice) {
561                 case 1:
562                     {
563                         //Secure resource discovery.
564
565                         pUnownedDevList.clear();
566                         std::cout << "Started discovery..." <<std::endl;
567                         OCStackResult result = OCSecure::discoverUnownedDevices(DISCOVERY_TIMEOUT,
568                                 pUnownedDevList);
569                         if (result != OC_STACK_OK)
570                         {
571                             std::cout<< "!!Error - UnOwned Discovery failed."<<std::endl;
572                         }
573                         else if (pUnownedDevList.size())
574                         {
575                             std::cout <<"Found secure devices, count = " <<
576                                 pUnownedDevList.size() << std::endl;
577                             printDevices(pUnownedDevList);
578                         }
579                         else
580                         {
581                             std::cout <<"No Secure devices found"<<std::endl;
582                         }
583                         break;
584                     }
585                 case 2:
586                     {
587                         pOwnedDevList.clear();
588                         std::cout << "Started discovery..." <<std::endl;
589                         OCStackResult result = OCSecure::discoverOwnedDevices(DISCOVERY_TIMEOUT,
590                                 pOwnedDevList);
591                         if (result != OC_STACK_OK)
592                         {
593                             std::cout<< "!!Error - Owned Discovery failed."<<std::endl;
594                         }
595                         else if (pOwnedDevList.size())
596                         {
597                             std::cout <<"Found owned devices, count = " <<
598                                 pOwnedDevList.size() << std::endl;
599                             printDevices(pOwnedDevList);
600                         }
601                         else
602                         {
603                             std::cout <<"No Secure devices found"<<std::endl;
604                         }
605                         break;
606                     }
607                 case 3:
608                     {
609                         unsigned int devNum;
610
611                         if (!pUnownedDevList.size())
612                         {
613                             std::cout <<"There are no more Unowned devices"<<std::endl;
614                             break;
615                         }
616
617                         for (unsigned int i = 0; i < pUnownedDevList.size(); i++ )
618                         {
619                             std::cout << i+1 << ": "<< pUnownedDevList[i]->getDeviceID();
620                             std::cout << " From IP:" << pUnownedDevList[i]->getDevAddr() <<std::endl;
621                         }
622
623                         std::cout <<"Select device number: "<<std::endl;
624                         std::cin >> devNum;
625                         if (devNum > pUnownedDevList.size())
626                         {
627                             std::cout <<"Invalid device number"<<std::endl;
628                             break;
629                         }
630                         transferDevIdx = devNum - 1;
631
632                         //register callbacks for JUST WORKS and PIN methods
633                         std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
634
635                         {
636                             OTMCallbackData_t justWorksCBData;
637                             justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
638                             justWorksCBData.createSecureSessionCB =
639                                 CreateSecureSessionJustWorksCallback;
640                             justWorksCBData.createSelectOxmPayloadCB =
641                                 CreateJustWorksSelectOxmPayload;
642                             justWorksCBData.createOwnerTransferPayloadCB =
643                                 CreateJustWorksOwnerTransferPayload;
644                             OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
645                                     &justWorksCBData, NULL);
646                         }
647
648                         {
649                             OTMCallbackData_t pinBasedCBData;
650                             pinBasedCBData.loadSecretCB = InputPinCodeCallback;
651                             pinBasedCBData.createSecureSessionCB =
652                                 CreateSecureSessionRandomPinCallbak;
653                             pinBasedCBData.createSelectOxmPayloadCB =
654                                 CreatePinBasedSelectOxmPayload;
655                             pinBasedCBData.createOwnerTransferPayloadCB =
656                                 CreatePinBasedOwnerTransferPayload;
657                             OCSecure::setOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN,
658                                     &pinBasedCBData, InputPinCB);
659                         }
660
661                         ask = 0;
662                         std::cout << "Transfering ownership for : "<<
663                             pUnownedDevList[devNum-1]->getDeviceID()<<std::endl;
664                         if (pUnownedDevList[devNum-1]->doOwnershipTransfer(ownershipTransferCB)
665                                 != OC_STACK_OK)
666                         {
667                             std::cout<<"OwnershipTransferCallback is failed"<<std::endl;
668                             ask = 1;
669                         }
670                         break;
671                     }
672                 case 4: //Provision ACL
673                     {
674                         int index;
675
676                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
677
678                         std::cout << "Provision ACL for : "<<
679                             pOwnedDevList[index]->getDeviceID()<< std::endl;
680
681                         acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
682                         if (NULL == acl1)
683                         {
684                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
685                             break;
686                         }
687
688                         std::cout << "Please input ACL for selected device: " << std::endl;
689                         if (0 != InputACL(acl1))
690                         {
691                             break;
692                         }
693
694                         ask = 0;
695
696                         if (pOwnedDevList[index]->provisionACL(acl1, provisionCB) != OC_STACK_OK)
697                         {
698                             ask = 1;
699                             std::cout <<"provisionACL is failed"<< std::endl;
700                         }
701                     }
702                     break;
703                 case 5: //Provision Credentials
704                     {
705                         int devices[2];
706
707                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
708
709                         int first  = devices[0];
710                         int second = devices[1];
711
712                         std::cout << "Provision Credentials to devices: "<<
713                             pOwnedDevList[first]->getDeviceID();
714                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
715
716                         Credential cred( NO_SECURITY_MODE ,0);
717                         std::cout << "Please input credentials for selected devices: " << std::endl;
718                         if (0 != InputCredentials(cred))
719                             break;
720
721                         ask = 0;
722
723                         if (pOwnedDevList[first]->provisionCredentials(cred,
724                                     *pOwnedDevList[second].get(), provisionCB) != OC_STACK_OK)
725                         {
726                             ask = 1;
727                             std::cout <<"provisionCredentials is failed"<< std::endl;
728                         }
729                     }
730                     break;
731                 case 6: //Provision ACL & Creds b/w two devices.
732                     {
733                         int devices[2];
734
735                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
736
737                         int first  = devices[0];
738                         int second = devices[1];
739
740                         std::cout << "Provision pairwise devices: "<<
741                             pOwnedDevList[first]->getDeviceID();
742                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
743
744                         Credential cred( NO_SECURITY_MODE, 0);
745                         std::cout << "Please input credentials for selected devices: " << std::endl;
746                         if (0 != InputCredentials(cred))
747                             break;
748
749                         acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
750                         if (NULL == acl1)
751                         {
752                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
753                             break;
754                         }
755
756                         std::cout << "Please input ACL for selected device: " << std::endl;
757                         if (0 != InputACL(acl1))
758                         {
759                             break;
760                         }
761
762                         acl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
763                         if (NULL == acl2)
764                         {
765                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
766                             break;
767                         }
768
769                         std::cout << "Please input ACL for selected device: " << std::endl;
770                         if (0 != InputACL(acl2))
771                         {
772                             break;
773                         }
774
775                         ask = 0;
776
777                         if (pOwnedDevList[first]->provisionPairwiseDevices(cred, acl1,
778                                     *pOwnedDevList[second].get(), acl2, provisionCB) != OC_STACK_OK)
779                         {
780                             ask = 1;
781                             std::cout <<"provisionPairwiseDevices is failed"<< std::endl;
782                         }
783                     }
784                     break;
785                 case 7: //Unlink Devices
786                     {
787                         int devices[2];
788
789                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
790
791                         int first  = devices[0];
792                         int second = devices[1];
793
794                         std::cout << "Unlink devices: "<< pOwnedDevList[first]->getDeviceID();
795                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
796
797                         ask = 0;
798
799                         if (pOwnedDevList[first]->unlinkDevices(*pOwnedDevList[second].get(),
800                                     provisionCB) != OC_STACK_OK)
801                         {
802                             ask = 1;
803                             std::cout <<"unlinkDevice is failed"<< std::endl;
804                         }
805                         break;
806                     }
807                 case 8: //Remove Device
808                     {
809                         int index;
810
811                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
812
813                         std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
814
815                         ask = 0;
816
817                         if (pOwnedDevList[index]->removeDevice(DISCOVERY_TIMEOUT, provisionCB)
818                                 != OC_STACK_OK)
819                         {
820                             ask = 1;
821                             std::cout <<"removeDevice is failed"<< std::endl;
822                         }
823                         break;
824                     }
825                 case 9: //Get Linked devices
826                     {
827                         UuidList_t linkedUuid;
828                         unsigned int devNum;
829
830                         if (!pOwnedDevList.size())
831                         {
832                             std::cout <<"There are no Owned devices yet,"
833                                 " may need to discover"<<std::endl;
834                             break;
835                         }
836
837                         for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
838                         {
839                             std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
840                             std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
841                         }
842
843                         std::cout <<"Select device number: "<<std::endl;
844                         std::cin >> devNum;
845                         if (devNum > pOwnedDevList.size())
846                         {
847                             std::cout <<"Invalid device number"<<std::endl;
848                             break;
849                         }
850
851                         if(pOwnedDevList[devNum  -1]->getLinkedDevices(linkedUuid) == OC_STACK_OK)
852                         {
853                             if (!linkedUuid.size())
854                             {
855                                 std::cout <<"No devices are linked to "<<
856                                     pOwnedDevList[devNum  -1]->getDeviceID() << std::endl;
857                             }
858                             //display the Linked devices (UUIDs)
859                             for(unsigned int i = 0; i < linkedUuid.size(); i++)
860                             {
861                                 printUuid(linkedUuid[i]);
862                             }
863                         }
864                         else
865                         {
866                             std::cout <<"Error! in getLinkedDevices"<<std::endl;
867                         }
868                         break;
869                     }
870                 case 10: //Get device' status
871                     {
872                         DeviceList_t unownedList, ownedList;
873
874                         if (OCSecure::getDevInfoFromNetwork(DISCOVERY_TIMEOUT, ownedList,
875                                     unownedList) == OC_STACK_OK)
876                         {
877                             std::cout <<"Owned Device' status for" <<std::endl;
878                             for (unsigned int i = 0; i < ownedList.size(); i++ )
879                             {
880                                 std::cout << "Device "<<i+1 <<" ID: '";
881                                 std::cout << ownedList[i]->getDeviceID() << "' From IP: ";
882                                 std::cout << ownedList[i]->getDevAddr() << " Status: ";
883                                 printStatus(ownedList[i]->getDeviceStatus());
884                             }
885                             std::cout <<"\nUnOwned Device' status for" <<std::endl;
886                             for (unsigned int i = 0; i < unownedList.size(); i++ )
887                             {
888                                 std::cout << "Device "<<i+1 <<" ID: '";
889                                 std::cout << unownedList[i]->getDeviceID() << "' From IP: ";
890                                 std::cout << unownedList[i]->getDevAddr() << " Status: ";
891                                 printStatus(unownedList[i]->getDeviceStatus());
892                             }
893
894                         }
895                         break;
896                     }
897
898                 case 11:
899                 default:
900                     out = 1;
901                     break;
902             }
903         }
904     }
905     catch(OCException& e)
906     {
907         oclog() << "Exception in main: "<<e.what();
908     }
909
910     return 0;
911 }