Add two APIs in EnrolleeConf class
[platform/upstream/iotivity.git] / service / easy-setup / sampleapp / mediator / linux / richsdk_sample / mediator.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 <iostream>
22 #include <condition_variable>
23
24 #include "OCPlatform.h"
25 #include "OCApi.h"
26 #include "OCProvisioningManager.hpp"
27 #include "securevirtualresourcetypes.h"
28
29 #include "EasySetup.hpp"
30 #include "ESRichCommon.h"
31
32 #define ES_SAMPLE_APP_TAG "ES_SAMPLE_APP_TAG"
33 #define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC }
34
35 #define JSON_DB_PATH "./oic_svr_db_client.dat"
36
37 using namespace OC;
38 using namespace OIC::Service;
39
40 static std::shared_ptr<RemoteEnrollee> remoteEnrollee = nullptr;
41 static std::shared_ptr<OC::OCResource> curResource = nullptr;
42
43 static std::mutex g_discoverymtx;
44 static std::condition_variable g_cond;
45
46 typedef void (*Runner)();
47
48 Runner g_currentRun;
49
50 int processUserInput(int min = std::numeric_limits<int>::min(),
51         int max = std::numeric_limits<int>::max())
52 {
53     assert(min <= max);
54
55     int input = 0;
56
57     std::cin >> input;
58     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
59
60     if (!std::cin.fail() && min <= input && input <= max)
61     {
62         return input;
63     }
64
65     std::cin.clear();
66     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
67
68     throw std::runtime_error("Invalid Input, please try again");
69 }
70
71 void printConfiguration(const EnrolleeConf& conf)
72 {
73     cout << "===========================================" << endl;
74     cout << "\tProvStatus : " << conf.getProvStatus() << endl;
75     cout << "\tLastErrCode : " << conf.getLastErrCode() << endl;
76     cout << "\tDevice Name : " << conf.getDeviceName() << endl;
77     cout << "\tModel Number : " << conf.getModelNumber() << endl;
78
79     for(auto it : conf.getWiFiModes())
80     {
81         cout << "\tSupported WiFi modes : " << it << endl;
82     }
83
84     cout << "\tSupported WiFi freq : " << static_cast<int>(conf.getWiFiFreq()) << endl;
85     cout << "\tCloud accessibility: " << conf.isCloudAccessible() << endl;
86     cout << "===========================================" << endl;
87 }
88
89 void printStatus(const EnrolleeStatus& status)
90 {
91     cout << "===========================================" << endl;
92     cout << "\tProvStatus : " << status.getProvStatus() << endl;
93     cout << "\tLastErrCode : " << status.getLastErrCode() << endl;
94     cout << "===========================================" << endl;
95 }
96
97 ESOwnershipTransferData provisionSecurityStatusCallback(std::shared_ptr<SecProvisioningStatus> secProvisioningStatus)
98 {
99     cout << "provisionSecurityStatusCallback IN" << endl;
100     cout << "ESResult : " << secProvisioningStatus->getESResult() << std::endl;
101     cout << "Device ID : " << secProvisioningStatus->getDeviceUUID() << std::endl;
102
103     if(secProvisioningStatus->getESResult() == ES_SECURE_RESOURCE_IS_DISCOVERED)
104     {
105 #ifdef __WITH_DTLS__
106         cout << "Owned Status : " << secProvisioningStatus->isOwnedDevice() << std::endl;
107         if(secProvisioningStatus->isOwnedDevice())
108         {
109             cout << "Owner ID : " << secProvisioningStatus->getOwnerID() << std::endl;
110         }
111         cout << "OT Method : " << secProvisioningStatus->getSelectedOTMethod() << std::endl;
112 #ifdef MULTIPLE_OWNER
113         cout << "MOT Enabled : " << secProvisioningStatus->isMOTEnabled() << std::endl;
114
115         // TEST
116         ESOwnershipTransferData OTData;
117         OTData.setMOTMethod(OIC_PRECONFIG_PIN, "12345678");
118
119         cout << "Enter!" << std::endl;
120         getchar();
121
122         return OTData;
123 #endif
124 #endif
125     }
126     else if(secProvisioningStatus->getESResult() == ES_OK)
127     {
128         cout << "provisionSecurity is success." << std::endl;
129     }
130     else
131     {
132         cout << "provisionSecurity is failed." << endl;
133     }
134
135     return {};
136 }
137
138 void provisionSecurity()
139 {
140     if(!remoteEnrollee)
141     {
142         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
143         return;
144     }
145
146     try
147     {
148         remoteEnrollee->provisionSecurity((SecurityProvStatusCbWithOption)provisionSecurityStatusCallback);
149     }
150     catch (OCException &e)
151     {
152         std::cout << "Exception during provisionSecurity call" << e.reason();
153         return;
154     }
155 }
156
157 void getStatusCallback(std::shared_ptr< GetEnrolleeStatus > getEnrolleeStatus)
158 {
159     if(getEnrolleeStatus->getESResult() != ES_OK)
160     {
161       cout << "getStatus is failed." << endl;
162       return;
163     }
164     else
165     {
166       cout << "getStatus is success." << endl;
167       printStatus(getEnrolleeStatus->getEnrolleeStatus());
168     }
169 }
170
171
172 void getStatus()
173 {
174     if(!remoteEnrollee)
175     {
176         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
177         return;
178     }
179
180     try
181     {
182         remoteEnrollee->getStatus(getStatusCallback);
183     }
184     catch (OCException &e)
185     {
186         std::cout << "Exception during getConfiguration call" << e.reason();
187         return;
188     }
189 }
190
191 void getConfigurationCallback(std::shared_ptr< GetConfigurationStatus > getConfigurationStatus)
192 {
193     if(getConfigurationStatus->getESResult() != ES_OK)
194     {
195       cout << "GetConfigurationStatus is failed." << endl;
196       return;
197     }
198     else
199     {
200       cout << "GetConfigurationStatus is success." << endl;
201       printConfiguration(getConfigurationStatus->getEnrolleeConf());
202     }
203 }
204
205 void getConfiguration()
206 {
207     if(!remoteEnrollee)
208     {
209         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
210         return;
211     }
212
213     try
214     {
215         remoteEnrollee->getConfiguration(getConfigurationCallback);
216     }
217     catch (OCException &e)
218     {
219         std::cout << "Exception during getConfiguration call" << e.reason();
220         return;
221     }
222 }
223
224 void deviceProvisioningStatusCallback(std::shared_ptr< DevicePropProvisioningStatus > provStatus)
225 {
226     if(provStatus->getESResult() != ES_OK)
227     {
228       cout << "Device Provisioning is failed." << endl;
229       return;
230     }
231     else
232     {
233       cout << "Device Provisioning is success." << endl;
234     }
235 }
236
237 void provisionDeviceProperty()
238 {
239     if(!remoteEnrollee)
240     {
241         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
242         return;
243     }
244
245     DeviceProp devProp;
246     devProp.setWiFiProp("Iotivity_SSID", "Iotivity_PWD", WPA2_PSK, TKIP_AES);
247     devProp.setDevConfProp("korean", "Korea", "Location");
248
249     try
250     {
251         remoteEnrollee->provisionDeviceProperties(devProp, deviceProvisioningStatusCallback);
252     }
253     catch (OCException &e)
254     {
255         std::cout << "Exception during provisionDeviceProperties call" << e.reason();
256         return;
257     }
258 }
259
260 void connectRequestStatusCallback(std::shared_ptr< ConnectRequestStatus > requestStatus)
261 {
262     if(requestStatus->getESResult() != ES_OK)
263     {
264       cout << "Request to connection is failed." << endl;
265       return;
266     }
267     else
268     {
269       cout << "Request to connection is success." << endl;
270     }
271 }
272
273 void requestToConnect()
274 {
275     if(!remoteEnrollee)
276     {
277         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
278         return;
279     }
280
281     try
282     {
283         std::vector<ES_CONNECT_TYPE> types;
284         types.push_back(ES_CONNECT_WIFI);
285         types.push_back(ES_CONNECT_COAPCLOUD);
286         remoteEnrollee->requestToConnect(types, connectRequestStatusCallback);
287     }
288     catch (OCException &e)
289     {
290         std::cout << "Exception during provisionDeviceProperties call" << e.reason();
291         return;
292     }
293 }
294
295 void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
296 {
297     switch (provStatus->getESResult())
298     {
299         case ES_OK:
300             cout << "Cloud Provisioning is success." << endl;
301             break;
302         case ES_SECURE_RESOURCE_DISCOVERY_FAILURE:
303             cout << "Enrollee is not found in a given network." << endl;
304             break;
305         case ES_ACL_PROVISIONING_FAILURE:
306             cout << "ACL provisioning is failed." << endl;
307             break;
308         case ES_CERT_PROVISIONING_FAILURE:
309             cout << "CERT provisioning is failed." << endl;
310             break;
311         default:
312             cout << "Cloud Provisioning is failed." << endl;
313             break;
314     }
315 }
316
317 void provisionCloudProperty()
318 {
319     if(!remoteEnrollee)
320     {
321         std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
322         return;
323     }
324
325     CloudProp cloudProp;
326     cloudProp.setCloudPropWithAccessToken("accessToken", OAUTH_TOKENTYPE_BEARER, "authProvider", "ciServer");
327     cloudProp.setCloudID("f002ae8b-c42c-40d3-8b8d-1927c17bd1b3");
328     cloudProp.setCredID(1);
329
330     try
331     {
332         remoteEnrollee->provisionCloudProperties(cloudProp, cloudProvisioningStatusCallback);
333     }
334     catch (OCException &e)
335     {
336         std::cout << "Exception during provisionCloudProperties call" << e.reason();
337         return;
338     }
339 }
340
341 // Callback to found resources
342 void foundResource(std::shared_ptr<OC::OCResource> resource)
343 {
344     std::string resourceURI;
345     std::string hostAddress;
346     try
347     {
348         // Do some operations with resource object.
349         if(resource &&
350            !curResource &&
351            resource->getResourceTypes().at(0) == OC_RSRVD_ES_RES_TYPE_EASYSETUP)
352         {
353             std::cout<<"DISCOVERED Resource:"<<std::endl;
354             // Get the resource URI
355             resourceURI = resource->uri();
356             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
357
358             // Get the resource host address
359             hostAddress = resource->host();
360             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
361
362             // Get the resource types
363             std::cout << "\tList of resource types: " << std::endl;
364             for(auto &resourceTypes : resource->getResourceTypes())
365             {
366                 std::cout << "\t\t" << resourceTypes << std::endl;
367             }
368
369             // Get the resource interfaces
370             std::cout << "\tList of resource interfaces: " << std::endl;
371             for(auto &resourceInterfaces : resource->getResourceInterfaces())
372             {
373                 std::cout << "\t\t" << resourceInterfaces << std::endl;
374             }
375
376             if(curResource == nullptr)
377             {
378                 remoteEnrollee = EasySetup::getInstance()->createRemoteEnrollee(resource);
379                 if(!remoteEnrollee)
380                 {
381                     std::cout << "RemoteEnrollee object is failed for some reasons!" << std::endl;
382                 }
383                 else
384                 {
385                     curResource = resource;
386                     std::cout << "RemoteEnrollee object is successfully created!" << std::endl;
387                     g_cond.notify_all();
388                 }
389             }
390         }
391     }
392     catch(std::exception& e)
393     {
394         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
395     }
396 }
397
398 void discoveryEnrolleeResource()
399 {
400     try
401     {
402         std::ostringstream requestURI;
403         requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << OC_RSRVD_ES_RES_TYPE_EASYSETUP;
404         OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
405         std::cout<< "Finding Resource... " <<std::endl;
406
407         std::unique_lock<std::mutex> lck(g_discoverymtx);
408         g_cond.wait_for(lck, std::chrono::seconds(5));
409     }
410     catch (OCException &e)
411     {
412         std::cout << "Exception in discoveryEnrolleeResource: "<<e.what();
413     }
414 }
415
416 void DisplayMenu()
417 {
418     constexpr int DISCOVERY_ENROLLEE = 1;
419     constexpr int PROVISION_SECURITY = 2;
420     constexpr int GET_STATUS = 3;
421     constexpr int GET_CONFIGURATION = 4;
422     constexpr int PROVISION_DEVICE_PROPERTY = 5;
423     constexpr int REQUEST_TO_CONNECT = 6;
424     constexpr int PROVISION_CLOUD_PROPERTY = 7;
425
426     std::cout << "========================================================\n";
427     std::cout << DISCOVERY_ENROLLEE << ". Discovery Enrollee Resource \n";
428     std::cout << PROVISION_SECURITY << ". Provision Security to Enrollee  \n";
429     std::cout << GET_STATUS << ". Get Status from Enrollee  \n";
430     std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee  \n";
431     std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
432     std::cout << REQUEST_TO_CONNECT << ". Request to Connect  \n";
433     std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property  \n";
434     std::cout << "========================================================\n";
435
436     int selection = processUserInput(DISCOVERY_ENROLLEE, PROVISION_CLOUD_PROPERTY);
437
438     switch (selection)
439     {
440         case DISCOVERY_ENROLLEE:
441             discoveryEnrolleeResource();
442             break;
443         case PROVISION_SECURITY:
444             provisionSecurity();
445             break;
446         case GET_STATUS:
447             getStatus();
448             break;
449         case GET_CONFIGURATION:
450             getConfiguration();
451             break;
452         case PROVISION_DEVICE_PROPERTY:
453             provisionDeviceProperty();
454             break;
455         case REQUEST_TO_CONNECT:
456             requestToConnect();
457             break;
458         case PROVISION_CLOUD_PROPERTY:
459             provisionCloudProperty();
460             break;
461         default:
462             break;
463     };
464 }
465
466 static FILE* client_open(const char *path, const char *mode)
467 {
468     if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
469     {
470         return fopen(JSON_DB_PATH, mode);
471     }
472     else
473     {
474         return fopen(path, mode);
475     }
476 }
477
478 int main()
479 {
480     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
481
482     PlatformConfig config
483     {
484         OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::HighQos, &ps
485     };
486
487     OCPlatform::Configure(config);
488
489     try
490     {
491 #ifdef __WITH_DTLS__
492         //Initializing the provisioning client stack using the db path provided by the application.
493         OCStackResult result = OCSecure::provisionInit("");
494
495         if (result != OC_STACK_OK)
496         {
497             return -1;
498         }
499 #endif
500     }catch (...)
501     {
502         std::cout << "Exception in main: " << std::endl;
503     }
504
505     while (true)
506     {
507         try
508         {
509             DisplayMenu();
510         }
511         catch (...)
512         {
513             std::cout << "Exception caught in main " << std::endl;
514         }
515     }
516
517     std::cout << "Stopping the client" << std::endl;
518
519     return 0;
520 }
521