replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / service / easy-setup / sampleapp / mediator / linux-samsung / richsdk_sample / mediator_sc.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
28 #include "EasySetup.hpp"
29 #include "ESSCCommon.h"
30
31 #define ES_SAMPLE_APP_TAG "ES_SAMPLE_APP_TAG"
32 #define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC }
33
34 #define JSON_DB_PATH "./oic_svr_db_client.dat"
35
36 using namespace OC;
37 using namespace OIC::Service;
38
39 static std::shared_ptr<RemoteEnrollee> remoteEnrollee = nullptr;
40 static std::shared_ptr<OC::OCResource> curResource = nullptr;
41
42 static std::mutex g_discoverymtx;
43 static std::condition_variable g_cond;
44
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 SCEnrolleeConf& conf)
72 {
73     cout << "===========================================" << endl;
74     cout << "\tDevice Name : " << conf.getDeviceName() << endl;
75     cout << "\tModel Number : " << conf.getModelNumber() << endl;
76
77     for(auto it : conf.getWiFiModes())
78     {
79         cout << "\tSupported WiFi modes : " << it << endl;
80     }
81
82     cout << "\tSupported WiFi freq : " << static_cast<int>(conf.getWiFiFreq()) << endl;
83     cout << "\tCloud accessibility: " << conf.isCloudAccessible() << endl;
84     cout << "\tDevice Type: " << conf.getDeviceType() << endl;
85     cout << "\tDevice Sub-Type: " << conf.getDeviceSubType() << endl;
86     cout << "\tRegister Set Device: " << conf.getRegisterSetDevice() << endl;
87     cout << "\tNetwork Provisioning Info: " << conf.getNetworkProvisioningInfo() << endl;
88     cout << "\tPnP Pin: " << conf.getPnpPin() << endl;
89     cout << "\tNetwork Connection State : " << conf.getNetConnectionState() << endl;
90     cout << "\tBSSID : " << conf.getBSSID() << endl;
91     cout << "\tUTC time: " << conf.getUTCDatetime() << endl;
92     cout << "\tRegional time: " << conf.getRegionalDatetime() << endl;
93     cout << "\tEasy Setup Protocol Version: " << conf.getESProtocolVersion() << endl;
94     cout << "===========================================" << endl;
95 }
96
97 void printStatus(const SCEnrolleeStatus& status)
98 {
99     cout << "===========================================" << endl;
100     cout << "\tProvStatus : " << status.getProvStatus() << endl;
101     cout << "\tLastErrCode : " << status.getLastErrCode() << endl;
102     cout << "\tNetwork Connection State : " << status.getNetConnectionState() << endl;
103     cout << "===========================================" << endl;
104 }
105
106 void provisionSecurityStatusCallback(std::shared_ptr<SecProvisioningStatus> secProvisioningStatus)
107 {
108     if(secProvisioningStatus->getESResult() != ES_OK)
109     {
110       cout << "provisionSecurity is failed." << endl;
111       return;
112     }
113     else
114     {
115       cout << "provisionSecurity is success." << endl;
116       cout << "uuid : " << secProvisioningStatus->getDeviceUUID()<< endl;
117     }
118 }
119
120 void provisionSecurity()
121 {
122     try
123     {
124     remoteEnrollee->provisionSecurity((SecurityProvStatusCb)provisionSecurityStatusCallback);
125     }
126     catch (OCException &e)
127     {
128         std::cout << "Exception during provisionSecurity call" << e.reason();
129         return;
130     }
131 }
132
133 void getStatusCallback(std::shared_ptr< GetEnrolleeStatus > getEnrolleeStatus)
134 {
135     if(getEnrolleeStatus->getESResult() != ES_OK)
136     {
137       cout << "getStatus is failed." << endl;
138       return;
139     }
140     else
141     {
142       cout << "getStatus is success." << endl;
143       printStatus(std::move(getEnrolleeStatus->getEnrolleeStatus()));
144     }
145 }
146
147
148 void getStatus()
149 {
150     if(!remoteEnrollee)
151     {
152         return;
153     }
154
155     try
156     {
157         remoteEnrollee->getStatus(getStatusCallback);
158     }
159     catch (OCException &e)
160     {
161         std::cout << "Exception during getConfiguration call" << e.reason();
162         return;
163     }
164 }
165
166 void getConfigurationCallback(std::shared_ptr< GetConfigurationStatus > getConfigurationStatus)
167 {
168     if(getConfigurationStatus->getESResult() != ES_OK)
169     {
170       cout << "GetConfigurationStatus is failed." << endl;
171       return;
172     }
173     else
174     {
175       cout << "GetConfigurationStatus is success." << endl;
176       printConfiguration(std::move(getConfigurationStatus->getEnrolleeConf()));
177     }
178 }
179
180 void getConfiguration()
181 {
182     if(!remoteEnrollee)
183     {
184         return;
185     }
186
187     try
188     {
189         remoteEnrollee->getConfiguration(getConfigurationCallback);
190     }
191     catch (OCException &e)
192     {
193         std::cout << "Exception during getConfiguration call" << e.reason();
194         return;
195     }
196 }
197
198 void deviceProvisioningStatusCallback(std::shared_ptr< DevicePropProvisioningStatus > provStatus)
199 {
200     if(provStatus->getESResult() != ES_OK)
201     {
202       cout << "Device Provisioning is failed." << endl;
203       return;
204     }
205     else
206     {
207       cout << "Device Provisioning is success." << endl;
208     }
209 }
210
211 void provisionDeviceProperty()
212 {
213     if(!remoteEnrollee)
214     {
215         return;
216     }
217
218     SCDeviceProp scDevProp;
219     scDevProp.setWiFiProp("Iotivity_SSID", "Iotivity_PWD", WPA2_PSK, TKIP_AES);
220     scDevProp.setDevConfProp("korean", "Korea", "Location");
221     scDevProp.setDiscoveryChannel(11);
222     scDevProp.setBSSID("aa:aa:aa:aa:aa:aa");
223
224     std::vector<std::string> locations;
225     locations.push_back("addr=Seoul, Rep. of Korea");
226     locations.push_back("zip=02848");
227     locations.push_back("bd=apartment");
228     scDevProp.setSCLocation(locations);
229     scDevProp.setRegisterMobileDevice("{\"wm\":\"00:11:22:33:44:55\",\"pm\":\"00:11:22:33:44:55\",\"bm\":\"00:11:22:33:44:55\",\"dt\":\"0\",\"it\":\"0\"}");
230
231     // Set UTC and regional date
232     time_t t = time(NULL);
233
234     char utcTimeStr[33] = {0};
235     struct tm *utcTime = gmtime(&t);
236     snprintf(utcTimeStr, 33, "[%04d]-[%02d]-[%02d]T[%02d]:[%02d]:[%02d]Z",
237         utcTime->tm_year+1900, utcTime->tm_mon+1, utcTime->tm_mday, utcTime->tm_hour, utcTime->tm_min, utcTime->tm_sec);
238
239     char localTimeStr[33] = {0};
240     struct tm *localTime = localtime(&t);
241     snprintf(localTimeStr, 33, "[%04d]-[%02d]-[%02d]T[%02d]:[%02d]:[%02d]Z",
242         localTime->tm_year+1900, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec);
243
244     scDevProp.setUTCDatetime(utcTimeStr);
245     scDevProp.setRegionalDatetime(localTimeStr);
246
247     try
248     {
249         remoteEnrollee->provisionDeviceProperties(scDevProp, deviceProvisioningStatusCallback);
250     }
251     catch (OCException &e)
252     {
253         std::cout << "Exception during provisionDeviceProperties call" << e.reason();
254         return;
255     }
256 }
257
258 void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
259 {
260     switch (provStatus->getESResult())
261     {
262         case ES_OK:
263             cout << "Cloud Provisioning is success." << endl;
264             break;
265         case ES_SECURE_RESOURCE_DISCOVERY_FAILURE:
266             cout << "Enrollee is not found in a given network." << endl;
267             break;
268         case ES_ACL_PROVISIONING_FAILURE:
269             cout << "ACL provisioning is failed." << endl;
270             break;
271         case ES_CERT_PROVISIONING_FAILURE:
272             cout << "CERT provisioning is failed." << endl;
273             break;
274         default:
275             cout << "Cloud Provisioning is failed." << endl;
276             break;
277     }
278 }
279
280 void provisionCloudProperty()
281 {
282     if(!remoteEnrollee)
283     {
284         return;
285     }
286
287     SCCloudProp cloudProp;
288     cloudProp.setCloudProp("authCode", "authProvider", "ciServer");
289     cloudProp.setCloudID("f002ae8b-c42c-40d3-8b8d-1927c17bd1b3");
290     cloudProp.setCredID(1);
291     cloudProp.setClientID("166135d296");
292
293     try
294     {
295         remoteEnrollee->provisionCloudProperties(cloudProp, cloudProvisioningStatusCallback);
296     }
297     catch (OCException &e)
298     {
299         std::cout << "Exception during provisionCloudProperties call" << e.reason();
300         return;
301     }
302 }
303
304 void DisplayMenu()
305 {
306     constexpr int PROVISION_SECURITY = 1;
307     constexpr int GET_STATUS = 2;
308     constexpr int GET_CONFIGURATION = 3;
309     constexpr int PROVISION_DEVICE_PROPERTY = 4;
310     constexpr int PROVISION_CLOUD_PROPERTY = 5;
311
312     std::cout << "========================================================\n";
313     std::cout << PROVISION_SECURITY << ". Provision Security to Enrollee  \n";
314     std::cout << GET_STATUS << ". Get Status from Enrollee  \n";
315     std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee  \n";
316     std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
317     std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property  \n";
318     std::cout << "========================================================\n";
319
320     int selection = processUserInput(PROVISION_SECURITY, PROVISION_CLOUD_PROPERTY);
321
322     switch (selection)
323     {
324         case PROVISION_SECURITY:
325             provisionSecurity();
326             break;
327         case GET_STATUS:
328             getStatus();
329             break;
330         case GET_CONFIGURATION:
331             getConfiguration();
332             break;
333         case PROVISION_DEVICE_PROPERTY:
334             provisionDeviceProperty();
335             break;
336         case PROVISION_CLOUD_PROPERTY:
337             provisionCloudProperty();
338             break;
339         default:
340             break;
341     };
342 }
343
344 // Callback to found resources
345 void foundResource(std::shared_ptr<OC::OCResource> resource)
346 {
347     std::string resourceURI;
348     std::string hostAddress;
349     try
350     {
351         // Do some operations with resource object.
352         if(resource &&
353            !curResource &&
354            resource->getResourceTypes().at(0) == OC_RSRVD_ES_RES_TYPE_EASYSETUP)
355         {
356             std::cout<<"DISCOVERED Resource:"<<std::endl;
357             // Get the resource URI
358             resourceURI = resource->uri();
359             std::cout << "\tURI of the resource: " << resourceURI << std::endl;
360
361             // Get the resource host address
362             hostAddress = resource->host();
363             std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
364
365             // Get the resource types
366             std::cout << "\tList of resource types: " << std::endl;
367             for(auto &resourceTypes : resource->getResourceTypes())
368             {
369                 std::cout << "\t\t" << resourceTypes << std::endl;
370             }
371
372             // Get the resource interfaces
373             std::cout << "\tList of resource interfaces: " << std::endl;
374             for(auto &resourceInterfaces : resource->getResourceInterfaces())
375             {
376                 std::cout << "\t\t" << resourceInterfaces << std::endl;
377             }
378
379             if(curResource == nullptr)
380             {
381                 remoteEnrollee = EasySetup::getInstance()->createRemoteEnrollee(resource);
382                 if(!remoteEnrollee)
383                 {
384                     std::cout << "RemoteEnrollee object is failed for some reasons!" << std::endl;
385                 }
386                 else
387                 {
388                     curResource = resource;
389                     std::cout << "RemoteEnrollee object is successfully created!" << std::endl;
390                     g_cond.notify_all();
391                 }
392             }
393         }
394     }
395     catch(std::exception &e)
396     {
397         std::cerr << "Exception in foundResource: "<< e.what() << std::endl;
398     }
399 }
400
401 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
402 {
403     (void)UNUSED_PARAM;
404     return fopen(JSON_DB_PATH, mode);
405 }
406
407 int main()
408 {
409     std::ostringstream requestURI;
410     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
411
412     PlatformConfig config
413     {
414         OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::HighQos, &ps
415     };
416
417     OCPlatform::Configure(config);
418
419     try
420     {
421 #ifdef __WITH_DTLS__
422         //Initializing the provisioning client stack using the db path provided by the application.
423         OCStackResult result = OCSecure::provisionInit("");
424
425         if (result != OC_STACK_OK)
426         {
427             return -1;
428         }
429 #endif
430
431         requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << OC_RSRVD_ES_RES_TYPE_EASYSETUP;
432
433         OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
434         std::cout<< "Finding Resource... " <<std::endl;
435
436         std::unique_lock<std::mutex> lck(g_discoverymtx);
437         g_cond.wait_for(lck, std::chrono::seconds(4));
438
439     }
440     catch(...)
441     {
442         oclog() << "Exception in main";
443     }
444
445     while (true)
446     {
447         try
448         {
449             DisplayMenu();
450         }
451         catch (...)
452         {
453             std::cout << "Exception caught in main";
454         }
455     }
456
457     std::cout << "Stopping the client" << std::endl;
458
459     return 0;
460 }
461