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