Add more descriptive log messages in easy setup
[platform/upstream/iotivity.git] / service / easy-setup / mediator / richsdk / src / RemoteEnrollee.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 "RemoteEnrollee.h"
22 #include "EnrolleeResource.h"
23 #include "CloudResource.h"
24 #include "OCPlatform.h"
25 #include "ESException.h"
26 #include "logger.h"
27 #include "OCResource.h"
28 #ifdef __WITH_DTLS__
29 #include "EnrolleeSecurity.h"
30 #include "base64.h"
31 #include "oic_malloc.h"
32 #endif //__WITH_DTLS
33
34 namespace OIC
35 {
36     namespace Service
37     {
38         static const char ES_BASE_RES_URI[] = "/oic/res";
39         #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE"
40         #define DISCOVERY_TIMEOUT 5
41
42         RemoteEnrollee::RemoteEnrollee(const std::shared_ptr< OC::OCResource > resource)
43         {
44             m_ocResource = resource;
45             m_enrolleeResource = std::make_shared<EnrolleeResource>(m_ocResource);
46             m_securityProvStatusCb = nullptr;
47             m_getConfigurationStatusCb = nullptr;
48             m_securityPinCb = nullptr;
49             m_secProvisioningDbPathCb = nullptr;
50             m_devicePropProvStatusCb = nullptr;
51             m_cloudPropProvStatusCb = nullptr;
52
53             m_deviceId = resource->sid();
54         }
55
56         void RemoteEnrollee::securityStatusHandler(
57                 const std::shared_ptr< SecProvisioningStatus > status) const
58         {
59             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "securityStatusHandlr IN");
60             OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "UUID = %s, ESResult = %d",
61                     status->getDeviceUUID().c_str(), status->getESResult());
62
63             if(status->getESResult() == ES_OK)
64             {
65                 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership transfer is successfully done.");
66                 m_securityProvStatusCb(status);
67             }
68             else
69             {
70                 OIC_LOG(ERROR, ES_REMOTE_ENROLLEE_TAG, "Ownership transfer is failed.");
71                 m_securityProvStatusCb(status);
72             }
73             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "securityStatusHandlr OUT");
74         }
75
76         void RemoteEnrollee::getStatusHandler(
77                 const std::shared_ptr< GetEnrolleeStatus > status) const
78         {
79             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler IN");
80
81             OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler = %d",
82                                                     status->getESResult());
83             m_getStatusCb(status);
84
85             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getStatusHandler OUT");
86         }
87
88         void RemoteEnrollee::getConfigurationStatusHandler (
89                 const std::shared_ptr< GetConfigurationStatus > status) const
90         {
91             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getConfigurationStatusHandler IN");
92
93             OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d",
94                                                     status->getESResult());
95             m_getConfigurationStatusCb(status);
96
97             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getConfigurationStatusHandler OUT");
98         }
99
100         void RemoteEnrollee::devicePropProvisioningStatusHandler(
101                 const std::shared_ptr< DevicePropProvisioningStatus > status) const
102         {
103             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "devicePropProvisioningStatusHandler IN");
104
105             OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "ProvStatus = %d", status->getESResult());
106             m_devicePropProvStatusCb(status);
107
108             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "devicePropProvisioningStatusHandler OUT");
109         }
110
111         void RemoteEnrollee::cloudPropProvisioningStatusHandler (
112                 const std::shared_ptr< CloudPropProvisioningStatus > status) const
113         {
114             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "cloudPropProvisioningStatusHandler IN");
115
116             OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d",
117                                                     status->getESResult());
118             m_cloudPropProvStatusCb(status);
119
120             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "cloudPropProvisioningStatusHandler OUT");
121         }
122
123         void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
124         {
125             OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered IN");
126
127             try
128             {
129                 if(resource)
130                 {
131                     if(!(resource->connectivityType() & CT_ADAPTER_TCP))
132                     {
133                         std::string resourceURI;
134                         std::string hostAddress;
135                         std::string hostDeviceID;
136
137                         // Get the resource URI
138                         resourceURI = resource->uri();
139                         OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
140                                 "URI of the resource: %s", resourceURI.c_str());
141
142                         // Get the resource host address
143                         hostAddress = resource->host();
144                         OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
145                                 "Host address of the resource: %s", hostAddress.c_str());
146
147                         hostDeviceID = resource->sid();
148                         OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
149                                 "Host DeviceID of the resource: %s", hostDeviceID.c_str());
150
151                         if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
152                         {
153                             OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "Find matched resource for cloud provisioning");
154                             m_ocResource = resource;
155                             m_discoveryResponse = true;
156                             m_cond.notify_all();
157                         }
158                     }
159                 }
160             }
161             catch(std::exception& e)
162             {
163                 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
164                         "Exception in foundResource: %s", e.what());
165             }
166
167             OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered OUT");
168         }
169
170         ESResult RemoteEnrollee::discoverResource()
171         {
172             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "discoverResource IN");
173
174             std::string query("");
175             query.append(ES_BASE_RES_URI);
176             query.append("?rt=");
177             query.append(OC_RSRVD_ES_RES_TYPE_PROV);
178
179             OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
180
181             m_discoveryResponse = false;
182
183             std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
184                     std::bind(&RemoteEnrollee::onDeviceDiscovered, this,
185                                                     std::placeholders::_1);
186             OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
187                     onDeviceDiscoveredCb);
188
189             if (result != OCStackResult::OC_STACK_OK)
190             {
191                 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
192                         "Failed discoverResource");
193                 return ES_ERROR;
194             }
195
196             std::unique_lock<std::mutex> lck(m_discoverymtx);
197             m_cond.wait_for(lck, std::chrono::seconds(DISCOVERY_TIMEOUT));
198
199             if (!m_discoveryResponse)
200             {
201                 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
202                         "Failed discoverResource because timeout");
203                 return ES_ERROR;
204             }
205
206             return ES_OK;
207         }
208
209         void RemoteEnrollee::provisionSecurity(const SecurityProvStatusCb callback)
210         {
211             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity IN");
212 #ifdef __WITH_DTLS__
213             ESResult res = ESResult::ES_ERROR;
214             if(!callback)
215             {
216                 throw ESInvalidParameterException("Callback is empty");
217             }
218             m_securityProvStatusCb = callback;
219
220             SecurityProvStatusCb securityProvStatusCb = std::bind(
221                     &RemoteEnrollee::securityStatusHandler,
222                     this,
223                     std::placeholders::_1);
224             //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
225             if(!m_enrolleeSecurity.get())
226             {
227                 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
228             }
229
230             res = m_enrolleeSecurity->provisionOwnership();
231
232             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
233                             std::make_shared< SecProvisioningStatus >(m_enrolleeSecurity->getUUID(), res);
234             m_securityProvStatusCb(securityProvisioningStatus);
235             m_enrolleeSecurity.reset();
236 #else
237             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured built.");
238
239             if(!callback)
240             {
241                 throw ESInvalidParameterException("Callback is empty");
242             }
243             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
244                      std::make_shared< SecProvisioningStatus >
245                                    ("", ESResult::ES_SEC_OPERATION_IS_NOT_SUPPORTED);
246             callback(securityProvisioningStatus);
247 #endif
248             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionSecurity OUT");
249         }
250
251         void RemoteEnrollee::getStatus(const GetStatusCb callback)
252         {
253             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getStatus IN");
254
255             if(!callback)
256             {
257                 throw ESInvalidParameterException("Callback is empty");
258             }
259
260             if (m_enrolleeResource == nullptr)
261             {
262                 throw ESBadRequestException ("Device not created");
263             }
264
265             m_getStatusCb = callback;
266
267             GetStatusCb getStatusCb = std::bind(
268                 &RemoteEnrollee::getStatusHandler, this, std::placeholders::_1);
269             m_enrolleeResource->registerGetStatusCallback(getStatusCb);
270             m_enrolleeResource->getStatus();
271
272             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getStatus OUT");
273         }
274
275         void RemoteEnrollee::getConfiguration(const GetConfigurationStatusCb callback)
276         {
277             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getConfiguration IN");
278
279             if(!callback)
280             {
281                 throw ESInvalidParameterException("Callback is empty");
282             }
283
284             if (m_enrolleeResource == nullptr)
285             {
286                 throw ESBadRequestException ("Device not created");
287             }
288
289             m_getConfigurationStatusCb = callback;
290
291             GetConfigurationStatusCb getConfigurationStatusCb = std::bind(
292                     &RemoteEnrollee::getConfigurationStatusHandler, this, std::placeholders::_1);
293             m_enrolleeResource->registerGetConfigurationStatusCallback(getConfigurationStatusCb);
294             m_enrolleeResource->getConfiguration();
295
296             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "getConfiguration OUT");
297         }
298
299         void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& deviceProp,
300                                                             const DevicePropProvStatusCb callback)
301         {
302             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionDeviceProperties IN");
303
304             if(!callback)
305             {
306                 throw ESInvalidParameterException("Callback is empty");
307             }
308
309             m_devicePropProvStatusCb = callback;
310
311             if (m_enrolleeResource == nullptr)
312             {
313                 throw ESBadRequestException ("Device not created");
314             }
315
316             if(deviceProp.getSsid().empty())
317             {
318                 throw ESBadRequestException ("Invalid Provisiong Data.");
319             }
320
321             DevicePropProvStatusCb devicePropProvStatusCb = std::bind(
322                     &RemoteEnrollee::devicePropProvisioningStatusHandler,
323                     this, std::placeholders::_1);
324
325             m_enrolleeResource->registerDevicePropProvStatusCallback(devicePropProvStatusCb);
326             m_enrolleeResource->provisionProperties(deviceProp);
327
328             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionDeviceProperties OUT");
329         }
330
331         void RemoteEnrollee::initCloudResource()
332         {
333             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "initCloudResource IN");
334
335             ESResult result = ES_ERROR;
336
337             result = discoverResource();
338
339             if (result == ES_ERROR)
340             {
341                 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
342                                     "Failed to create resource object using discoverResource");
343                 throw ESBadRequestException ("Resource object not created");
344             }
345
346             else
347             {
348                 if(m_ocResource != nullptr)
349                 {
350                     m_cloudResource = std::make_shared<CloudResource>(m_ocResource);
351                 }
352                 else
353                 {
354                     throw ESBadGetException ("Resource handle is invalid");
355                 }
356             }
357
358             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "initCloudResource OUT");
359         }
360
361         void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp,
362                                                             const CloudPropProvStatusCb callback)
363         {
364             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties IN");
365
366             if(!callback)
367             {
368                 throw ESInvalidParameterException("Callback is empty");
369             }
370
371             m_cloudPropProvStatusCb = callback;
372
373             if(cloudProp.getAuthCode().empty() ||
374                 cloudProp.getAuthProvider().empty() ||
375                 cloudProp.getCiServer().empty())
376             {
377                 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
378             }
379
380             try
381             {
382                 initCloudResource();
383             }
384
385             catch (const std::exception& e)
386             {
387                 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
388                     "Exception caught in provisionCloudProperties = %s", e.what());
389
390                 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
391                         CloudPropProvisioningStatus >(ESResult::ES_ENROLLEE_DISCOVERY_FAILURE);
392                 m_cloudPropProvStatusCb(provStatus);
393                 return;
394             }
395 #if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
396             if(!(cloudProp.getCloudID().empty() && cloudProp.getCredID() <= 0))
397             {
398                 ESResult res = ESResult::ES_ERROR;
399                 if(!m_enrolleeSecurity.get())
400                 {
401                     m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
402                 }
403
404
405                 res = m_enrolleeSecurity->provisionSecurityForCloudServer(cloudProp.getCloudID(),
406                                                                           cloudProp.getCredID());
407                 m_enrolleeSecurity.reset();
408                 if(res != ESResult::ES_OK)
409                 {
410                     m_cloudResource = nullptr;
411                     std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
412                             CloudPropProvisioningStatus >(res);
413                     m_cloudPropProvStatusCb(provStatus);
414                     return;
415                 }
416             }
417             else
418             {
419                 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "ACL and Cert. provisioning are skipped.");
420             }
421 #endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)
422
423             if (m_cloudResource == nullptr)
424             {
425                 throw ESBadRequestException ("Cloud Resource not created");
426             }
427
428             CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
429                     &RemoteEnrollee::cloudPropProvisioningStatusHandler,
430                                     this, std::placeholders::_1);
431
432             m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
433             m_cloudResource->provisionProperties(cloudProp);
434
435             OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties OUT");
436         }
437     }
438 }