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